diff --git a/.editorconfig b/.editorconfig index ef37151..6552fa9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -15,4 +15,12 @@ continuation_indent_size = 2 curly_bracket_next_line = false indent_brace_style = BSD spaces_around_operators = true -spaces_around_brackets = none \ No newline at end of file +spaces_around_brackets = none + +[*.mustache] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = false +insert_final_newline = false diff --git a/.github/workflows/actions/coverage/action.yml b/.github/workflows/actions/coverage/action.yml new file mode 100644 index 0000000..708c721 --- /dev/null +++ b/.github/workflows/actions/coverage/action.yml @@ -0,0 +1,46 @@ +name: Code Coverage Report +description: Generate code coverage report and publish them +inputs: + default-runtime-version: + description: "Version used to setup runtime" + required: true + codecov-secret: + description: "CodeCov secret token" + required: true + +runs: + using: "composite" + steps: + - name: Set up runtime - Node.js ${{ inputs.default-runtime-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.default-runtime-version }} + cache: 'npm' + + - name: Install dependencies + shell: bash + run: npm ci + + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - name: Generate OpenAPI client + shell: bash + run: npm run spec:generate + + - name: Run unit tests with coverage + shell: bash + run: npm run test:coverage:ci + + - name: Upload coverage to Codecov + if: success() + uses: codecov/codecov-action@v3 + with: + files: coverage.xml + flags: unittests + name: codecov-umbrella + fail_ci_if_error: true + slug: upsun/upsun-sdk-node + token: ${{ inputs.codecov-secret }} diff --git a/.github/workflows/actions/doc/action.yml b/.github/workflows/actions/doc/action.yml new file mode 100644 index 0000000..b27682f --- /dev/null +++ b/.github/workflows/actions/doc/action.yml @@ -0,0 +1,24 @@ +name: Generate Documentation +description: Generate documentation of the project +inputs: + default-runtime-version: + description: "Version used to setup runtime" + required: true + +runs: + using: "composite" + steps: + - name: Set up runtime - Node.js ${{ inputs.default-runtime-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.default-runtime-version }} + cache: 'npm' + + - name: Install dependencies + shell: bash + run: npm ci + + - name: Generate documentation (with docs generator) + if: false + shell: bash + run: npm run docs diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml new file mode 100644 index 0000000..eaa12ae --- /dev/null +++ b/.github/workflows/develop.yml @@ -0,0 +1,130 @@ +name: PR Code review + +on: + push: + branches: + - main + pull_request: + +env: + # Define the primary Node.js version for release, build, coverage uploads and badge generation + PRIMARY_NODE_VERSION: '25' + +jobs: + quality: + name: Code Quality + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up runtime - Node.js ${{ env.PRIMARY_NODE_VERSION }} + uses: actions/setup-node@v4 + with: + node-version: ${{ env.PRIMARY_NODE_VERSION }} + cache: 'npm' + + - name: Validate dependency file + run: npm install --dry-run + + - name: Install dependencies + run: npm ci + + - name: Run JS/TS lint (eslint, prettier) + run: npm run lint:all + + tests: + name: Test on Node.js ${{ matrix.node-version }} + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x, 22.x, 24.x] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up runtime - Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - name: Install OpenAPI Generator CLI + run: npm run spec:generate:install + + - name: Generate OpenAPI client + run: npm run spec:generate + + - name: Run unit tests + run: npm run test:unit + + doc: + name: Generate Documentation + runs-on: ubuntu-latest + needs: [ tests ] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: ./.github/workflows/actions/doc + with: + default-runtime-version: ${{ env.PRIMARY_NODE_VERSION }} + + coverage: + name: Code Coverage Report + runs-on: ubuntu-latest + needs: [ tests ] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: ./.github/workflows/actions/coverage + if: false + with: + default-runtime-version: ${{ env.PRIMARY_NODE_VERSION }} + codecov-secret: ${{ secrets.CODECOV_TOKEN || 'Please define a CODECOV_TOKEN in your GitHub envVars' }} + + build: + name: Build Project + runs-on: ubuntu-latest + needs: [ coverage, quality ] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up runtime - Node.js ${{ env.PRIMARY_NODE_VERSION }} + uses: actions/setup-node@v4 + with: + node-version: ${{ env.PRIMARY_NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - name: Install OpenAPI Generator CLI + run: npm run spec:generate:install + + - name: Generate OpenAPI client + run: npm run spec:generate + + - name: Build project + run: npm run build diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index ae66422..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: CI - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [16.x, 18.x, 20.x, 22.x] - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '21' - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - name: Install dependencies - run: npm ci - - name: Generate OpenAPI client - run: | - chmod +x ./scripts/gen_node.sh - ./scripts/gen_node.sh - - name: Build - run: npm run build - - # - name: Run linter - # run: npm run lint - - # - name: Run tests - # run: npm test \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4a0ddf7..bc0c167 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,35 +1,78 @@ -name: Publish Package to npmjs +name: Publish Release on: release: types: [published] +env: + # Define the primary Node.js version for release, build, coverage uploads and badge generation + PRIMARY_NODE_VERSION: '22' + jobs: - build: + doc: + name: Generate Documentation runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: ./.github/actions/doc + with: + default-runtime-version: ${{ env.PRIMARY_NODE_VERSION }} + + coverage: + name: Code Coverage Report + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: ./.github/actions/coverage + if: false + with: + default-runtime-version: ${{ env.PRIMARY_NODE_VERSION }} + codecov-secret: ${{ secrets.CODECOV_TOKEN || 'Please define a CODECOV_TOKEN in your GitHub envVars' }} + + publish: + name: Publish release to NPM + runs-on: ubuntu-latest + needs: [ doc, coverage ] permissions: contents: read id-token: write + steps: - - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up runtime - Node.js ${{ env.PRIMARY_NODE_VERSION }} + uses: actions/setup-node@v4 + with: + node-version: ${{ env.PRIMARY_NODE_VERSION }} + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: npm ci + - uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '21' - - uses: actions/setup-node@v4 - with: - node-version: '22.x' - registry-url: 'https://registry.npmjs.org' - - run: npm ci - - run: npm run gen-client - - run: npm run build - - run: npm publish + + - name: Install OpenAPI Generator CLI + run: npm run spec:generate:install + + - name: Generate OpenAPI client + run: npm run spec:generate + + - name: Build project + run: npm run build + + - name: Publish package + if: success() + run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - #TODO --access public --provenance when repo is public - # - uses: actions/setup-node@v4 - # with: - # registry-url: 'https://npm.pkg.github.com' - # - run: npm publish - # env: - # NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.gitignore b/.gitignore index c76409a..78c14b9 100644 --- a/.gitignore +++ b/.gitignore @@ -72,7 +72,7 @@ pids lib-cov # Coverage directory used by tools like istanbul -coverage +/coverage *.lcov # nyc test coverage @@ -235,5 +235,9 @@ $RECYCLE.BIN/ *.lnk # End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,node,linux,macos,windows - -src/apis-gen +!.github/** +src/.openapi-generator +openapitools.json +src/api/** +src/model/** +src/core/runtime.ts diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..98d9822 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +dist +node_modules +coverage +*.yaml +*.yml +*.json +src/api/** +src/model/** +!src/core/runtime.ts diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..f9941cb --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "bracketSpacing": true, + "arrowParens": "avoid" +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 765de69..d4391be 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,5 +2,6 @@ "files.exclude": { "**/*.js": { "when": "$(basename).ts" }, "**/**.js": { "when": "$(basename).tsx" } - } + }, + "search.useIgnoreFiles": false } diff --git a/README.md b/README.md index 096e8c1..ecceeb1 100644 --- a/README.md +++ b/README.md @@ -29,21 +29,25 @@ const result = await upsun.environment.redeploy("MyProjectId", "main"); ## Devel Clone repository: + ```bash git clone git@github.com:upsun/upsun-sdk-node.git ``` Install Dep: + ```bash npm install ``` Generate API Client (Low-level) base on OpenAPI spec. + ```bash npm run gen-client ``` Build the stack: + ```bash npm run build ``` diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..d307fe7 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,26 @@ +import eslint from '@eslint/js'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + eslint.configs.recommended, + ...tseslint.configs.recommended, + { + files: ['src/**/*.ts'], + languageOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + rules: { + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/explicit-function-return-type': 'warn', + '@typescript-eslint/no-explicit-any': 'warn', + '@typescript-eslint/no-var-requires': 'error', + 'no-console': 'warn', + 'prefer-const': 'error', + 'no-var': 'error', + }, + }, + { + ignores: ['dist/**', 'node_modules/**', 'coverage/**', 'tests/**'], + }, +); diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..31f3c5c --- /dev/null +++ b/jest.config.js @@ -0,0 +1,23 @@ +export default { + preset: 'ts-jest/presets/default-esm', + testEnvironment: 'node', + roots: ['/src', '/tests'], + testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'], + transform: { + '^.+\\.ts$': [ + 'ts-jest', + { + useESM: true, + tsconfig: 'tsconfig.test.json', + }, + ], + }, + extensionsToTreatAsEsm: ['.ts'], + moduleNameMapper: { + '^(\\.{1,2}/.*)\\.js$': '$1', + }, + setupFilesAfterEnv: ['/tests/setup.ts'], + collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts', '!src/apis-gen/**'], + coverageDirectory: 'coverage', + coverageReporters: ['text', 'lcov', 'html'], +}; diff --git a/package-lock.json b/package-lock.json index c07eeef..1a59581 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ }, "devDependencies": { "@eslint/js": "^9.35.0", - "@openapitools/openapi-generator-cli": "^2.23.1", "@types/jest": "^30.0.0", "@types/node": "^24.3.1", "eslint": "^9.35.0", @@ -59,6 +58,7 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -565,17 +565,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@borewit/text-codec": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.1.1.tgz", - "integrity": "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -837,51 +826,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.1.tgz", - "integrity": "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^2.1.0", - "iconv-lite": "^0.6.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, - "engines": { - "node": "20 || >=22" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1643,16 +1587,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@lukeed/csprng": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", - "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/@mark.probst/typescript-json-schema": { "version": "0.55.0", "resolved": "https://registry.npmjs.org/@mark.probst/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz", @@ -1747,92 +1681,6 @@ "@tybys/wasm-util": "^0.10.0" } }, - "node_modules/@nestjs/axios": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-4.0.1.tgz", - "integrity": "sha512-68pFJgu+/AZbWkGu65Z3r55bTsCPlgyKaV4BSG8yUAD72q1PPuyVRgUwFv6BxdnibTUHlyxm06FmYWNC+bjN7A==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^10.0.0 || ^11.0.0", - "axios": "^1.3.1", - "rxjs": "^7.0.0" - } - }, - "node_modules/@nestjs/common": { - "version": "11.1.6", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.6.tgz", - "integrity": "sha512-krKwLLcFmeuKDqngG2N/RuZHCs2ycsKcxWIDgcm7i1lf3sQ0iG03ci+DsP/r3FcT/eJDFsIHnKtNta2LIi7PzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "file-type": "21.0.0", - "iterare": "1.2.1", - "load-esm": "1.0.2", - "tslib": "2.8.1", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "class-transformer": ">=0.4.1", - "class-validator": ">=0.13.2", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/core": { - "version": "11.1.6", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.6.tgz", - "integrity": "sha512-siWX7UDgErisW18VTeJA+x+/tpNZrJewjTBsRPF3JVxuWRuAB1kRoiJcxHgln8Lb5UY9NdvklITR84DUEXD0Cg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@nuxt/opencollective": "0.4.1", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "8.2.0", - "tslib": "2.8.1", - "uid": "2.0.2" - }, - "engines": { - "node": ">= 20" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^11.0.0", - "@nestjs/microservices": "^11.0.0", - "@nestjs/platform-express": "^11.0.0", - "@nestjs/websockets": "^11.0.0", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - }, - "@nestjs/websockets": { - "optional": true - } - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1871,49 +1719,6 @@ "node": ">= 8" } }, - "node_modules/@nuxt/opencollective": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.4.1.tgz", - "integrity": "sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "consola": "^3.2.3" - }, - "bin": { - "opencollective": "bin/opencollective.js" - }, - "engines": { - "node": "^14.18.0 || >=16.10.0", - "npm": ">=5.10.0" - } - }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" - }, - "bin": { - "opencollective": "bin/opencollective.js" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/@nuxtjs/opencollective/node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "dev": true, - "license": "MIT" - }, "node_modules/@open-draft/deferred-promise": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", @@ -1939,43 +1744,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@openapitools/openapi-generator-cli": { - "version": "2.23.1", - "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.23.1.tgz", - "integrity": "sha512-Kd5EZqzbcIXf6KRlpUrheHMzQNRHsJWzAGrm4ncWCNhnQl+Mh6TsFcqq+hIetgiFCknWBH6cZ2f37SxPxaon4w==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@nestjs/axios": "4.0.1", - "@nestjs/common": "11.1.6", - "@nestjs/core": "11.1.6", - "@nuxtjs/opencollective": "0.3.2", - "axios": "1.11.0", - "chalk": "4.1.2", - "commander": "8.3.0", - "compare-versions": "4.1.4", - "concurrently": "9.2.1", - "console.table": "0.10.0", - "fs-extra": "11.3.1", - "glob": "11.0.3", - "inquirer": "8.2.7", - "proxy-agent": "6.5.0", - "reflect-metadata": "0.2.2", - "rxjs": "7.8.2", - "tslib": "2.8.1" - }, - "bin": { - "openapi-generator-cli": "main.js" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/openapi_generator" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -2027,39 +1795,6 @@ "@sinonjs/commons": "^3.0.1" } }, - "node_modules/@tokenizer/inflate": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", - "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "fflate": "^0.8.2", - "token-types": "^6.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true, - "license": "MIT" - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -2276,6 +2011,7 @@ "integrity": "sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.43.0", "@typescript-eslint/types": "8.43.0", @@ -2783,6 +2519,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2813,16 +2550,6 @@ "node": ">=0.4.0" } }, - "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2920,38 +2647,6 @@ "node": ">=6" } }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/babel-jest": { "version": "30.1.2", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.1.2.tgz", @@ -3081,16 +2776,6 @@ ], "license": "MIT" }, - "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -3104,18 +2789,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3167,6 +2840,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001716", "electron-to-chromium": "^1.5.149", @@ -3203,31 +2877,6 @@ "node-int64": "^0.4.0" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3235,20 +2884,6 @@ "dev": true, "license": "MIT" }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -3333,13 +2968,6 @@ "node": ">=10" } }, - "node_modules/chardet": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz", - "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==", - "dev": true, - "license": "MIT" - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -3401,42 +3029,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 10" - } - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3470,16 +3062,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -3525,19 +3107,6 @@ "dev": true, "license": "MIT" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", @@ -3590,23 +3159,6 @@ "node": ">=12.17" } }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/compare-versions": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.4.tgz", - "integrity": "sha512-FemMreK9xNyL8gQevsdRMrvO4lFCkQP7qbuktn1q8ndcNk1+0mz7lgE7b/sNvbhVgY4w6tMN1FDp6aADjqw2rw==", - "dev": true, - "license": "MIT" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3614,74 +3166,10 @@ "dev": true, "license": "MIT" }, - "node_modules/concurrently": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", - "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "4.1.2", - "rxjs": "7.8.2", - "shell-quote": "1.8.3", - "supports-color": "8.1.1", - "tree-kill": "1.2.2", - "yargs": "17.7.2" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" - } - }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/console.table": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/console.table/-/console.table-0.10.0.tgz", - "integrity": "sha512-dPyZofqggxuvSf7WXvNjuRfnsOk1YazkVP8FdxH4tcH2c37wc79/Yl6Bhr7Lsu00KMgy2ql/qCMuNu8xctZM8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "easy-table": "1.1.0" - }, - "engines": { - "node": "> 0.10" - } - }, - "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==", + "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" }, @@ -3717,16 +3205,6 @@ "node": ">= 8" } }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -3777,44 +3255,6 @@ "node": ">=0.10.0" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -3847,21 +3287,6 @@ "url": "https://dotenvx.com" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3869,16 +3294,6 @@ "dev": true, "license": "MIT" }, - "node_modules/easy-table": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.0.tgz", - "integrity": "sha512-oq33hWOSSnl2Hoh00tZWaIPi1ievrD9aFG82/IgjlycAnW9hHx5PkJiXpxPsgEE+H7BsbVQXFVFST8TEXS6/pA==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "wcwidth": ">=1.0.1" - } - }, "node_modules/electron-to-chromium": { "version": "1.5.157", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.157.tgz", @@ -3916,55 +3331,6 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -3988,34 +3354,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, "node_modules/eslint": { "version": "9.35.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4302,13 +3647,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true, - "license": "MIT" - }, "node_modules/fastq": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", @@ -4329,39 +3667,6 @@ "bser": "2.1.1" } }, - "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/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -4375,25 +3680,6 @@ "node": ">=16.0.0" } }, - "node_modules/file-type": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz", - "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tokenizer/inflate": "^0.2.7", - "strtok3": "^10.2.2", - "token-types": "^6.0.0", - "uint8array-extras": "^1.4.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -4458,27 +3744,6 @@ "dev": true, "license": "ISC" }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -4509,38 +3774,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs-extra": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", - "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4563,16 +3796,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4593,31 +3816,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -4628,20 +3826,6 @@ "node": ">=8.0.0" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -4655,45 +3839,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-uri": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", - "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/glob": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", - "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.3.1", - "jackspeak": "^4.1.1", - "minimatch": "^10.0.3", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -4707,22 +3852,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -4736,19 +3865,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4806,48 +3922,6 @@ "node": ">=8" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -4855,34 +3929,6 @@ "dev": true, "license": "MIT" }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -4893,19 +3939,6 @@ "node": ">=10.17.0" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -5010,47 +4043,6 @@ "dev": true, "license": "ISC" }, - "node_modules/inquirer": { - "version": "8.2.7", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.7.tgz", - "integrity": "sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/external-editor": "^1.0.0", - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^6.0.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5114,16 +4106,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-node-process": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", @@ -5154,19 +4136,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-url": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", @@ -5270,38 +4239,13 @@ "dev": true, "license": "MIT" }, - "node_modules/iterare": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", - "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=6" - } - }, - "node_modules/jackspeak": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", - "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/jest": { "version": "30.1.3", "resolved": "https://registry.npmjs.org/jest/-/jest-30.1.3.tgz", "integrity": "sha512-Ry+p2+NLk6u8Agh5yVqELfUJvRfV51hhVBRIB5yZPY7mU0DGBmOuFG5GebZbMbm86cdQNK0fhJuDX8/1YorISQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "30.1.3", "@jest/types": "30.0.5", @@ -6090,13 +5034,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, - "license": "MIT" - }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -6152,23 +5089,10 @@ "dev": true, "license": "MIT", "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" + "json5": "lib/cli.js" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=6" } }, "node_modules/keyv": { @@ -6212,26 +5136,6 @@ "dev": true, "license": "MIT" }, - "node_modules/load-esm": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/load-esm/-/load-esm-1.0.2.tgz", - "integrity": "sha512-nVAvWk/jeyrWyXEAs84mpQCYccxRqgKY4OznLuJhJCa0XsPSfdOIr2zvBZEj3IHEHbX97jjscKRRV539bW0Gpw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - }, - { - "type": "buymeacoffee", - "url": "https://buymeacoffee.com/borewit" - } - ], - "license": "MIT", - "engines": { - "node": ">=13.2.0" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -6276,33 +5180,6 @@ "dev": true, "license": "MIT" }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.1.tgz", - "integrity": "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -6336,16 +5213,6 @@ "tmpl": "1.0.5" } }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -6377,29 +5244,6 @@ "node": ">=8.6" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -6460,13 +5304,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true, - "license": "ISC" - }, "node_modules/napi-postinstall": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", @@ -6497,16 +5334,6 @@ "dev": true, "license": "MIT" }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/nock": { "version": "14.0.10", "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.10.tgz", @@ -6676,30 +5503,6 @@ "node": ">= 0.8.0" } }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/outvariant": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", @@ -6749,40 +5552,6 @@ "node": ">=6" } }, - "node_modules/pac-proxy-agent": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", - "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.6", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.5" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "dev": true, - "license": "MIT", - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -6866,33 +5635,6 @@ "node": ">=8" } }, - "node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -7076,43 +5818,6 @@ "node": ">= 8" } }, - "node_modules/proxy-agent": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", - "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.6", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.1.0", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.5" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true, - "license": "MIT" - }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -7406,13 +6111,6 @@ "node": ">=8.10.0" } }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7456,20 +6154,6 @@ "node": ">=4" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -7481,16 +6165,6 @@ "node": ">=0.10.0" } }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7515,16 +6189,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -7556,13 +6220,6 @@ "node": ">=10" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, "node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", @@ -7599,19 +6256,6 @@ "node": ">=8" } }, - "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -7642,47 +6286,6 @@ "node": ">=8" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", - "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7704,13 +6307,6 @@ "source-map": "^0.6.0" } }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -7883,23 +6479,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strtok3": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", - "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tokenizer/token": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -7990,13 +6569,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, "node_modules/tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", @@ -8024,25 +6596,6 @@ "node": ">=8.0" } }, - "node_modules/token-types": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz", - "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@borewit/text-codec": "^0.1.0", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/touch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", @@ -8060,16 +6613,6 @@ "dev": true, "license": "MIT" }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -8198,7 +6741,8 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "0BSD" + "license": "0BSD", + "optional": true }, "node_modules/type-check": { "version": "0.4.0", @@ -8298,32 +6842,6 @@ "node": ">=0.8.0" } }, - "node_modules/uid": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", - "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@lukeed/csprng": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/uint8array-extras": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", - "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -8367,16 +6885,6 @@ "dev": true, "license": "MIT" }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/unrs-resolver": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", @@ -8510,16 +7018,6 @@ "makeerror": "1.0.12" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -8581,21 +7079,6 @@ "node": ">=12.17" } }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", diff --git a/package.json b/package.json index f370c9f..8171e86 100644 --- a/package.json +++ b/package.json @@ -9,29 +9,54 @@ "dist" ], "scripts": { + "help": "bash ./scripts/help.sh", "clean": "rm -rf dist", - "run": "node dist/index.js", - "build": "tsc -p tsconfig.json ", + "run": "node dist/app.js", + "build": "tsc -p tsconfig.json", "build:watch": "tsc --watch", - "lint": "eslint . --ext .ts", - "lint:fix": "eslint . --ext .ts --fix", - "prettier": "prettier --write .", - "prettier:check": "prettier --check .", - "gen-client": "./scripts/gen_node.sh", + "lint:es": "eslint . --ext .ts", + "lint:prettier": "prettier --check .", + "fix:es": "eslint . --ext .ts --fix", + "fix:prettier": "prettier --write .", "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage", - "test:unit": "jest --testPathPattern=unit", - "test:integration": "jest --testPathPattern=integration", - "release-version": "bash ./scripts/release-version.sh $npm_config_tag" + "test:coverage:ci": "jest --coverage --ci", + "test:unit": "jest --testPathPatterns=unit", + "test:integration": "jest --testPathPatterns=integration", + "spec:clean": "rm -Rf src/api/* ; rm -Rf src/model/* ; rm -Rf src/core/runtime.ts", + "spec:dl": "wget -O ./schema/openapispec-upsun.json 'https://meta.upsun.com/openapi-spec?sdks=true'", + "spec:patch": "sed -i 's/HTTP access permissions/Http access permissions/g' ./schema/openapispec-upsun.json", + "spec:generate:install": "npm install -g @openapitools/openapi-generator-cli", + "spec:generate": "npx openapi-generator-cli generate -c templates/config.yaml", + "release-version": "bash ./scripts/release-version.sh $npm_config_tag", + "spec:full": "", + "lint:all": "npm run lint:es && npm run lint:prettier", + "fix:all": "npm run fix:es && npm run fix:prettier", + "test:all": "npm run test:unit", + "qa": "npm run lint:all && npm run test:all", + "qa:all": "npm run build && npm run lint:all && npm run test:all" }, "keywords": [], "author": "Mickael GAILLARD", + "contributors": [ + { + "name": "Mickael GAILLARD", + "email": "mickael.gaillard@upsun.com" + }, + { + "name": "Florent HUCK", + "email": "florent.huck@upsun.com" + }, + { + "name": "Upsun Advocacy Team", + "homepage": "https://www.upsun.com" + } + ], "license": "Apache v2.0", "description": "Upsun SDK for Node.js", "devDependencies": { "@eslint/js": "^9.35.0", - "@openapitools/openapi-generator-cli": "^2.23.1", "@types/jest": "^30.0.0", "@types/node": "^24.3.1", "eslint": "^9.35.0", @@ -47,5 +72,9 @@ }, "dependencies": { "dotenv": "^17.2.2" + }, + "repository": { + "type": "git", + "url": "https://github.com/upsun/upsun-sdk-node" } } diff --git a/schema/openapispec-upsun.json b/schema/openapispec-upsun.json new file mode 100644 index 0000000..dc8ea02 --- /dev/null +++ b/schema/openapispec-upsun.json @@ -0,0 +1,40432 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Upsun.com Rest API", + "version": "1.0", + "contact": { + "name": "Support", + "url": "https://upsun.com/contact-us/" + }, + "termsOfService": "https://upsun.com/trust-center/legal/tos/", + "description": "# Introduction\n\nUpsun, formerly Platform.sh, is a container-based Platform-as-a-Service. Our main API\nis simply Git. With a single `git push` and a couple of YAML files in\nyour repository you can deploy an arbitrarily complex cluster.\nEvery [**Project**](#tag/Project) can have multiple applications (PHP,\nNode.js, Python, Ruby, Go, etc.) and managed, automatically\nprovisioned services (databases, message queues, etc.).\n\nEach project also comes with multiple concurrent\nlive staging/development [**Environments**](#tag/Environment).\nThese ephemeral development environments\nare automatically created every time you push a new branch or create a\npull request, and each has a full copy of the data of its parent branch,\nwhich is created on-the-fly in seconds.\n\nOur Git implementation supports integrations with third party Git\nproviders such as GitHub, Bitbucket, or GitLab, allowing you to simply\nintegrate Upsun into your existing workflow.\n\n## Using the REST API\n\nIn addition to the Git API, we also offer a REST API that allows you to manage\nevery aspect of the platform, from managing projects and environments,\nto accessing accounts and subscriptions, to creating robust workflows\nand integrations with your CI systems and internal services.\n\nThese API docs are generated from a standard **OpenAPI (Swagger)** Specification document\nwhich you can find here in [YAML](openapispec-upsun.yaml) and in [JSON](openapispec-upsun.json) formats.\n\nThis RESTful API consumes and produces HAL-style JSON over HTTPS,\nand any REST library can be used to access it. On GitHub, we also host\na few API libraries that you can use to make API access easier, such as our\n[PHP API client](https://github.com/upsun/upsun-sdk-php).\n\nIn order to use the API you will first need to have an [Upsun account](https://auth.upsun.com/register/) \nand [create an API Token](https://docs.upsun.com/anchors/cli/api-token/).\n\n# Authentication\n\n## OAuth2\n\nAPI authentication is done with OAuth2 access tokens.\n\n### API tokens\n\nYou can use an API token as one way to get an OAuth2 access token. This\nis particularly useful in scripts, e.g. for CI pipelines.\n\nTo create an API token, go to the \"API Tokens\" section\nof the \"Account Settings\" tab on the [Console](https://console.upsun.com).\n\nTo exchange this API token for an access token, a `POST` request\nmust be made to `https://auth.upsun.com/oauth2/token`.\n\nThe request will look like this in cURL:\n\n
\ncurl -u platform-api-user: \\\n    -d 'grant_type=api_token&api_token=API_TOKEN' \\\n    https://auth.upsun.com/oauth2/token\n
\n\nThis will return a \"Bearer\" access token that\ncan be used to authenticate further API requests, for example:\n\n
\n{\n    \"access_token\": \"abcdefghij1234567890\",\n    \"expires_in\": 900,\n    \"token_type\": \"bearer\"\n}\n
\n\n### Using the Access Token\n\nTo authenticate further API requests, include this returned bearer token\nin the `Authorization` header. For example, to retrieve a list of\n[Projects](#tag/Project)\naccessible by the current user, you can make the following request\n(substituting the dummy token for your own):\n\n
\ncurl -H \"Authorization: Bearer abcdefghij1234567890\" \\\n    https://api.upsun.com/projects\n
\n\n# HAL Links\n\nMost endpoints in the API return fields which defines a HAL\n(Hypertext Application Language) schema for the requested endpoint.\nThe particular objects returns and their contents can vary by endpoint.\nThe payload examples we give here for the requests do not show these\nelements. These links can allow you to create a fully dynamic API client\nthat does not need to hardcode any method or schema.\n\nUnless they are used for pagination we do not show the HAL links in the\npayload examples in this documentation for brevity and as their content\nis contextual (based on the permissions of the user).\n\n## _links Objects\n\nMost endpoints that respond to `GET` requests will include a `_links` object\nin their response. The `_links` object contains a key-object pair labelled `self`, which defines\ntwo further key-value pairs:\n\n* `href` - A URL string referring to the fully qualified name of the returned object. For many endpoints, this will be the direct link to the API endpoint on the region gateway, rather than on the general API gateway. This means it may reference a host of, for example, `eu-2.platform.sh` rather than `api.upsun.com`.\n* `meta` - An object defining the OpenAPI Specification (OAS) [schema object](https://swagger.io/specification/#schemaObject) of the component returned by the endpoint.\n\nThere may be zero or more other fields in the `_links` object resembling fragment identifiers\nbeginning with a hash mark, e.g. `#edit` or `#delete`. Each of these keys\nrefers to a JSON object containing two key-value pairs:\n\n* `href` - A URL string referring to the path name of endpoint which can perform the action named in the key.\n* `meta` - An object defining the OAS schema of the endpoint. This consists of a key-value pair, with the key defining an HTTP method and the value defining the [operation object](https://swagger.io/specification/#operationObject) of the endpoint.\n\nTo use one of these HAL links, you must send a new request to the URL defined\nin the `href` field which contains a body defined the schema object in the `meta` field.\n\nFor example, if you make a request such as `GET /projects/abcdefghij1234567890`, the `_links`\nobject in the returned response will include the key `#delete`. That object\nwill look something like this fragment:\n\n```\n\"#delete\": {\n \"href\": \"/api/projects/abcdefghij1234567890\",\n \"meta\": {\n \"delete\": {\n \"responses\": {\n . . . // Response definition omitted for space\n },\n \"parameters\": []\n }\n }\n}\n```\n\nTo use this information to delete a project, you would then send a `DELETE`\nrequest to the endpoint `https://api.upsun.com/api/projects/abcdefghij1234567890`\nwith no body or parameters to delete the project that was originally requested.\n\n## _embedded Objects\n\nRequests to endpoints which create or modify objects, such as `POST`, `PATCH`, or `DELETE`\nrequests, will include an `_embedded` key in their response. The object\nrepresented by this key will contain the created or modified object. This\nobject is identical to what would be returned by a subsequent `GET` request\nfor the object referred to by the endpoint.\n", + "x-logo": { + "url": "https://docs.upsun.com/images/upsun-api.svg", + "href": "https://upsun.com/#section/Introduction", + "altText": "Upsun logo" + } + }, + "servers": [ + { + "url": "{schemes}://api.upsun.com", + "description": "The Upsun.com API gateway", + "variables": { + "schemes": { + "default": "https" + } + } + } + ], + "security": [ + { + "BearerAuth": [] + } + ], + "tags": [ + { + "name": "Cert Management", + "description": "User-supplied SSL/TLS certificates can be managed using these\nendpoints. You can now list and modify certificate provisioners\nusing the `/projects/{projectId}/provisioners` and\n`/projects/{projectId}/provisioners/{certificateProvisionerDocumentId}`\nendpoints. For more information, see our\n[Third-party TLS certificate](https://docs.upsun.com/anchors/domains/custom/custom-certificates/)\ndocumentation. These endpoints are not for managing certificates\nthat are automatically supplied by Upsun via Let's Encrypt.\n" + }, + { + "name": "Environment", + "description": "On Upsun, an environment encompasses a single instance of your\nentire application stack, the services used by the application,\nthe application's data storage, and the environment's backups.\n\nIn general, an environment represents a single branch or merge request\nin the Git repository backing a project. It is a virtual cluster\nof read-only application and service containers with read-write\nmounts for application and service data.\n\nOn Upsun, the default branch is your production environment\u2014thus,\nmerging changes to this branch will put those changes to production.\n" + }, + { + "name": "Environment Type", + "description": "Environment Types is the way Upsun manages access. We currently have 3 environment types:\n* Development\n* Staging\n* Production\n\nEach environment type will contain a group of users and their accesses. We manage access,\nadding, updating and removing users and their roles, here.\n\nEach environment will have a type, pointing to one of these 3 environment types.\nSee `type` in [Environments](#tag/Environment).\n\nIn general:\n* Production will be reserved for the default branch, and cannot be set manually.\n* An environment can be set to be type `staging` or development manually and when branching.\n\nDedicated Generation 2 projects have different rules for environment types. If your project\ncontains at least one of those Dedicated Generation 2 environments, the rules are slightly different:\n* All non-dedicated environments in your project can be `development` or `staging`, but never `production`.\n* Dedicated Generation 2 environments can be set either to `staging` or `production`, but never `development`.\n* The default branch is not considered to be a special case.\n" + }, + { + "name": "Environment Backups", + "description": "A snapshot is a complete backup of an environment, including all the\npersistent data from all services running in an environment and all\nfiles present in mounted volumes.\n\nThese endpoints can be used to trigger the creation of new backups,\nget information about existing backups, delete existing backups or\nrestore a backup.\nMore information about backups can be found in our\n[documentation](https://docs.upsun.com/anchors/environments/backup/).\n" + }, + { + "name": "Environment Variables", + "description": "These endpoints manipulate user-defined variables which are bound to a\nspecific environment, as well as (optionally) the children of an\nenvironment. These variables can be made available at both build time\nand runtime. For more information on environment variables,\nsee the [Variables](https://docs.upsun.com/anchors/variables/set/environment/create/)\nsection of the documentation.\n" + }, + { + "name": "Autoscaling", + "description": "Upsun provides native support for autoscaling, allowing your applications to automatically adjust based on resource usage.\nThis ensures that your apps remain responsive under load while helping you optimize costs.\nYou can configure thresholds for metrics such as CPU, RAM, and request latency. \nResources will automatically scale to meet demand.\nEach container profile assigned to an application or service provides a specific combination of CPU and RAM, which you can select via the Upsun UI or CLI.\n\nThese endpoints manage autoscaling configurations that are tied to a\nspecific environment, and optionally to its child environments.\nYou can define scaling rules based on metrics like CPU, memory, or\nrequest latency, and these rules will be applied at both build time\nand runtime. For more information on configuring autoscaling for your\nenvironments, see the [Autoscaling](https://docs.upsun.com/manage-resources/autoscaling.html) section\nof the documentation.\n" + }, + { + "name": "Project", + "description": "## Project Overview\n\nOn Upsun, a Project is backed by a single Git repository\nand encompasses your entire application stack, the services\nused by your application, the application's data storage,\nthe production and staging environments, and the backups of those\nenvironments.\n\nWhen you create a new project, you start with a single\n[Environment](#tag/Environment) called *Master*,\ncorresponding to the master branch in the Git repository of\nthe project\u2014this will be your production environment.\n\nIf you connect your project to an external Git repo\nusing one of our [Third-Party Integrations](#tag/Third-Party-Integrations)\na new development environment can be created for each branch\nor pull request created in the repository. When a new development\nenvironment is created, the production environment's data\nwill be cloned on-the-fly, giving you an isolated, production-ready\ntest environment.\n\nThis set of API endpoints can be used to retrieve a list of projects\nassociated with an API key, as well as create and update the parameters\nof existing projects.\n\n> **Note**:\n>\n> To list projects or to create a new project, use [`/subscriptions`](#tag/Subscriptions).\n" + }, + { + "name": "Project Variables", + "description": "These endpoints manipulate user-defined variables which are bound to an\nentire project. These variables are accessible to all environments\nwithin a single project, and they can be made available at both build\ntime and runtime. For more information on project variables,\nsee the [Variables](https://docs.upsun.com/anchors/variables/set/project/create/)\nsection of the documentation.\n" + }, + { + "name": "Project Settings", + "description": "These endpoints can be used to retrieve and manipulate project-level\nsettings. Only the `initialize` property can be set by end users. It is used\nto initialize a project from an existing Git repository.\n\nThe other properties can only be set by a privileged user.\n" + }, + { + "name": "Repository", + "description": "The Git repository backing projects hosted on Upsun can be\naccessed in a **read-only** manner through the `/projects/{projectId}/git/*`\nfamily of endpoints. With these endpoints, you can retrieve objects from\nthe Git repository in the same way that you would in a local environment.\n" + }, + { + "name": "Domain Management", + "description": "These endpoints can be used to add, modify, or remove domains from\na project. For more information on how domains function on\nUpsun, see the [Domains](https://docs.upsun.com/anchors/domains/custom/)\nsection of our documentation.\n" + }, + { + "name": "Routing", + "description": "These endpoints modify an environment's `routes:` section of the `.upsun/config.yaml` file.\nFor routes to propagate to child environments, the child environments\nmust be synchronized with their parent.\n\nMore information about routing can be found in the [Routes](https://docs.upsun.com/anchors/routes/)\nsection of the documentation.\n" + }, + { + "name": "Source Operations", + "description": "These endpoints interact with source code operations as defined in the `source.operations`\nkey in a project's `.upsun/config.yaml` configuration. More information\non source code operations is\n[available in our user documentation](https://docs.upsun.com/anchors/app/source-operations/).\n" + }, + { + "name": "Deployment Target", + "description": "Upsun is capable of deploying the production environments of\nprojects in multiple topologies: both in clusters of containers, and\nas dedicated virtual machines. This is an internal API that can\nonly be used by privileged users.\n" + }, + { + "name": "Deployments", + "description": "The deployments endpoints gives detailed information about the actual\ndeployment of an active environment. Currently, it returns the _current_\ndeployment with information about the different apps, services, and\nroutes contained within.\n" + }, + { + "name": "Third-Party Integrations", + "description": "Upsun can easily integrate with many third-party services, including\nGit hosting services (GitHub, GitLab, and Bitbucket),\nhealth notification services (email, Slack, PagerDuty),\nperformance analytics platforms (New Relic, Blackfire, Tideways),\nand webhooks.\n\nFor clarification about what information each field requires, see the\n[External Integrations](https://docs.upsun.com/anchors/integrations/)\ndocumentation. NOTE: The names of the CLI arguments listed in the\ndocumentation are not always named exactly the same as the\nrequired body fields in the API request.\n" + }, + { + "name": "MFA", + "description": "Multi-factor authentication (MFA) requires the user to present two (or more) types of evidence (or factors) to prove their identity.\n\nFor example, the evidence might be a password and a device-generated code, which show the user has the knowledge factor (\"something you know\") \nas well as the possession factor (\"something you have\"). In this way MFA offers good protection against the compromise of any single factor, \nsuch as a stolen password.\n\nUsing the MFA API you can set up time-based one-time passcodes (TOTP), which can be generated on a single registered device (\"something you have\") such as a mobile phone.\n" + }, + { + "name": "Subscriptions", + "description": "Each project is represented by a subscription that holds the plan information.\nThese endpoints can be used to go to a larger plan, add more storage, or subscribe to\noptional features.\n" + }, + { + "name": "Orders", + "description": "These endpoints can be used to retrieve order information from our billing\nsystem. Here you can view information about your bill for our services,\ninclude the billed amount and a link to a PDF of the bill.\n" + }, + { + "name": "Invoices", + "description": "These endpoints can be used to retrieve invoices from our billing system.\nAn invoice of type \"invoice\" is generated automatically every month, if the customer has active projects.\nInvoices of type \"credit_memo\" are a result of manual action when there was a refund or an invoice correction.\n" + }, + { + "name": "Vouchers", + "description": "These endpoints can be used to retrieve vouchers associated with a particular\nuser as well as apply a voucher to a particular user.\n" + }, + { + "name": "Records", + "description": "These endpoints retrieve information about which plans were assigned to a particular\nproject at which time.\n" + }, + { + "name": "Support", + "description": "These endpoints can be used to retrieve information about support ticket priority\nand allow you to submit new ticket to the Upsun Support Team.\n" + }, + { + "name": "System Information", + "description": "These endpoints can be used to retrieve low-level information and interact with the\ncore component of Upsun infrastructure.\n\nThis is an internal API that can only be used by privileged users.\n" + } + ], + "paths": { + "/alerts/subscriptions/{subscriptionId}/usage": { + "get": { + "tags": [ + "Alerts" + ], + "summary": "Get usage alerts for a subscription", + "operationId": "get-usage-alerts", + "parameters": [ + { + "$ref": "#/components/parameters/subscription_id" + } + ], + "responses": { + "200": { + "description": "The list of current and available alerts for the subscription.", + "content": { + "application/json": { + "schema": { + "properties": { + "available": { + "description": "The list of available usage alerts.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Alert" + } + }, + "current": { + "description": "The list of the current usage alerts.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Alert" + } + } + }, + "type": "object" + } + } + } + } + }, + "x-property-id-kebab": "get-usage-alerts", + "x-tag-id-kebab": "Alerts", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true + }, + "patch": { + "tags": [ + "Alerts" + ], + "summary": "Update usage alerts.", + "operationId": "update-usage-alerts", + "parameters": [ + { + "$ref": "#/components/parameters/subscription_id" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "alerts": { + "description": "The list of usage alerts to create or update.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Alert" + } + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "The list of current and available alerts for the subscription.", + "content": { + "application/json": { + "schema": { + "properties": { + "available": { + "description": "The list of available usage alerts.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Alert" + } + }, + "current": { + "description": "The list of the current usage alerts.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Alert" + } + } + }, + "type": "object" + } + } + } + } + }, + "x-property-id-kebab": "update-usage-alerts", + "x-tag-id-kebab": "Alerts", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true + } + }, + "/orders/download": { + "get": { + "tags": [ + "Orders" + ], + "summary": "Download an invoice.", + "operationId": "download-invoice", + "parameters": [ + { + "name": "token", + "in": "query", + "description": "JWT for invoice.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "An invoice PDF.", + "content": { + "application/pdf": {} + } + } + }, + "x-property-id-kebab": "download-invoice", + "x-tag-id-kebab": "Orders", + "x-return-types-displayReturn": false, + "x-return-types": [ + "string" + ], + "x-return-types-union": "string", + "x-phpdoc": { + "return": false + }, + "x-returnable": true + } + }, + "/discounts/{id}": { + "get": { + "tags": [ + "Discounts" + ], + "summary": "Get an organization discount", + "operationId": "get-discount", + "parameters": [ + { + "$ref": "#/components/parameters/discountId" + } + ], + "responses": { + "200": { + "description": "A discount object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Discount" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "get-discount", + "x-tag-id-kebab": "Discounts", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Discount" + ], + "x-return-types-union": "\\Upsun\\Model\\Discount", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Discount" + }, + "x-returnable": true + } + }, + "/discounts/types/allowance": { + "get": { + "tags": [ + "Discounts" + ], + "summary": "Get the value of the First Project Incentive discount", + "operationId": "get-type-allowance", + "responses": { + "200": { + "description": "A discount object", + "content": { + "application/json": { + "schema": { + "properties": { + "currencies": { + "description": "Discount values per currency.", + "properties": { + "EUR": { + "description": "Discount value in EUR.", + "properties": { + "formatted": { + "description": "The discount amount formatted.", + "type": "string" + }, + "amount": { + "description": "The discount amount.", + "type": "number", + "format": "float" + }, + "currency": { + "description": "The currency.", + "type": "string" + }, + "currency_symbol": { + "description": "Currency symbol.", + "type": "string" + } + }, + "type": "object" + }, + "USD": { + "description": "Discount value in USD.", + "properties": { + "formatted": { + "description": "The discount amount formatted.", + "type": "string" + }, + "amount": { + "description": "The discount amount.", + "type": "number", + "format": "float" + }, + "currency": { + "description": "The currency.", + "type": "string" + }, + "currency_symbol": { + "description": "Currency symbol.", + "type": "string" + } + }, + "type": "object" + }, + "GBP": { + "description": "Discount value in GBP.", + "properties": { + "formatted": { + "description": "The discount amount formatted.", + "type": "string" + }, + "amount": { + "description": "The discount amount.", + "type": "number", + "format": "float" + }, + "currency": { + "description": "The currency.", + "type": "string" + }, + "currency_symbol": { + "description": "Currency symbol.", + "type": "string" + } + }, + "type": "object" + }, + "AUD": { + "description": "Discount value in AUD.", + "properties": { + "formatted": { + "description": "The discount amount formatted.", + "type": "string" + }, + "amount": { + "description": "The discount amount.", + "type": "number", + "format": "float" + }, + "currency": { + "description": "The currency.", + "type": "string" + }, + "currency_symbol": { + "description": "Currency symbol.", + "type": "string" + } + }, + "type": "object" + }, + "CAD": { + "description": "Discount value in CAD.", + "properties": { + "formatted": { + "description": "The discount amount formatted.", + "type": "string" + }, + "amount": { + "description": "The discount amount.", + "type": "number", + "format": "float" + }, + "currency": { + "description": "The currency.", + "type": "string" + }, + "currency_symbol": { + "description": "Currency symbol.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "get-type-allowance", + "x-tag-id-kebab": "Discounts", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true + } + }, + "/me": { + "get": { + "tags": [ + "Users" + ], + "summary": "Get current logged-in user info", + "description": "Retrieve information about the currently logged-in user (the user associated with the access token).", + "operationId": "get-current-user-deprecated", + "responses": { + "200": { + "description": "The user object.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CurrentUser" + } + } + } + } + }, + "x-deprecated": true, + "x-property-id-kebab": "get-current-user-deprecated", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\CurrentUser" + ], + "x-return-types-union": "\\Upsun\\Model\\CurrentUser", + "x-phpdoc": { + "return": "\\Upsun\\Model\\CurrentUser" + }, + "x-returnable": true, + "x-description": [ + "Retrieve information about the currently logged-in user (the user associated with the access token)." + ] + } + }, + "/ssh_keys/{key_id}": { + "get": { + "tags": [ + "Ssh Keys" + ], + "summary": "Get an SSH key", + "operationId": "get-ssh-key", + "parameters": [ + { + "name": "key_id", + "in": "path", + "description": "The ID of the ssh key.", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "A single SSH public key record.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SshKey" + } + } + } + } + }, + "x-property-id-kebab": "get-ssh-key", + "x-tag-id-kebab": "Ssh-Keys", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\SshKey" + ], + "x-return-types-union": "\\Upsun\\Model\\SshKey", + "x-phpdoc": { + "return": "\\Upsun\\Model\\SshKey" + }, + "x-returnable": true + }, + "delete": { + "tags": [ + "Ssh Keys" + ], + "summary": "Delete an SSH key", + "operationId": "delete-ssh-key", + "parameters": [ + { + "name": "key_id", + "in": "path", + "description": "The ID of the ssh key.", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "204": { + "description": "Success." + } + }, + "x-property-id-kebab": "delete-ssh-key", + "x-tag-id-kebab": "Ssh-Keys", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false + } + }, + "/ssh_keys": { + "post": { + "tags": [ + "Ssh Keys" + ], + "summary": "Add a new public SSH key to a user", + "operationId": "create-ssh-key", + "requestBody": { + "content": { + "application/json": { + "schema": { + "required": [ + "value" + ], + "properties": { + "value": { + "description": "The value of the ssh key.", + "type": "string" + }, + "title": { + "description": "The title of the ssh key.", + "type": "string" + }, + "uuid": { + "description": "The uuid of the user.", + "type": "string" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "201": { + "description": "The newly created ssh key.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SshKey" + } + } + } + } + }, + "x-property-id-kebab": "create-ssh-key", + "x-tag-id-kebab": "Ssh-Keys", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\SshKey" + ], + "x-return-types-union": "\\Upsun\\Model\\SshKey", + "x-phpdoc": { + "return": "\\Upsun\\Model\\SshKey" + }, + "x-returnable": true + } + }, + "/me/phone": { + "post": { + "tags": [ + "Users" + ], + "summary": "Check if phone verification is required", + "description": "Find out if the current logged in user requires phone verification to create projects.", + "operationId": "get-current-user-verification-status", + "responses": { + "200": { + "description": "The information pertinent to determine if the account requires phone verification before project creation.", + "content": { + "application/json": { + "schema": { + "properties": { + "verify_phone": { + "description": "Does this user need to verify their phone number for project creation.", + "type": "boolean" + } + }, + "type": "object" + } + } + } + } + }, + "x-property-id-kebab": "get-current-user-verification-status", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Find out if the current logged in user requires phone verification to create projects." + ] + } + }, + "/me/verification": { + "post": { + "tags": [ + "Users" + ], + "summary": "Check if verification is required", + "description": "Find out if the current logged in user requires verification (phone or staff) to create projects.", + "operationId": "get-current-user-verification-status-full", + "responses": { + "200": { + "description": "The information pertinent to determine if the account requires any type of verification before project creation.", + "content": { + "application/json": { + "schema": { + "properties": { + "state": { + "description": "Does this user need verification for project creation.", + "type": "boolean" + }, + "type": { + "description": "What type of verification is needed (phone or ticket)", + "type": "string" + } + }, + "type": "object" + } + } + } + } + }, + "x-property-id-kebab": "get-current-user-verification-status-full", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Find out if the current logged in user requires verification (phone or staff) to create projects." + ] + } + }, + "/subscriptions/{subscriptionId}/can-update": { + "get": { + "tags": [ + "Subscriptions" + ], + "summary": "Checks if the user is able to update a project.", + "operationId": "can-update-subscription", + "parameters": [ + { + "$ref": "#/components/parameters/subscription_id" + }, + { + "$ref": "#/components/parameters/subscription_plan" + }, + { + "$ref": "#/components/parameters/subscription_environments" + }, + { + "$ref": "#/components/parameters/subscription_storage" + }, + { + "$ref": "#/components/parameters/subscription_user_licenses" + } + ], + "responses": { + "200": { + "description": "Check result with error message if presented", + "content": { + "application/json": { + "schema": { + "properties": { + "can_update": { + "description": "Boolean result of the check.", + "type": "boolean" + }, + "message": { + "description": "Details in case of negative check result.", + "type": "string" + }, + "required_action": { + "description": "Required action impeding project update.", + "type": "object" + } + }, + "type": "object" + } + } + } + } + }, + "x-property-id-kebab": "can-update-subscription", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true + } + }, + "/subscriptions/{subscriptionId}/can-afford": { + "post": { + "tags": [ + "Subscriptions" + ], + "summary": "Checks if the user can afford the requested resources.", + "operationId": "can-afford-subscription", + "parameters": [ + { + "$ref": "#/components/parameters/subscription_id" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "resources": { + "description": "A map of resource keys to quantities (both strings).", + "type": "object", + "additionalProperties": {} + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "Proposed resource change is affordable." + }, + "402": { + "description": "Proposed change is not affordable." + } + }, + "x-property-id-kebab": "can-afford-subscription", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false + } + }, + "/profiles": { + "get": { + "tags": [ + "User Profiles" + ], + "summary": "List user profiles", + "operationId": "list-profiles", + "responses": { + "200": { + "description": "The list of user profiles.", + "content": { + "application/json": { + "schema": { + "properties": { + "count": { + "description": "Total number of results.", + "type": "integer" + }, + "profiles": { + "description": "Array of user profiles.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Profile" + } + }, + "_links": { + "$ref": "#/components/schemas/HalLinks" + } + }, + "type": "object" + } + } + } + } + }, + "x-property-id-kebab": "list-profiles", + "x-tag-id-kebab": "User-Profiles", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true + } + }, + "/profiles/{userId}": { + "get": { + "tags": [ + "User Profiles" + ], + "summary": "Get a single user profile", + "operationId": "get-profile", + "parameters": [ + { + "$ref": "#/components/parameters/user_id" + } + ], + "responses": { + "200": { + "description": "A User profile object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Profile" + } + } + } + } + }, + "x-property-id-kebab": "get-profile", + "x-tag-id-kebab": "User-Profiles", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Profile" + ], + "x-return-types-union": "\\Upsun\\Model\\Profile", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Profile" + }, + "x-returnable": true + }, + "patch": { + "tags": [ + "User Profiles" + ], + "summary": "Update a user profile", + "description": "Update a user profile, supplying one or more key/value pairs to to change.", + "operationId": "update-profile", + "parameters": [ + { + "$ref": "#/components/parameters/user_id" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "display_name": { + "description": "The user's display name.", + "type": "string" + }, + "username": { + "description": "The user's username.", + "type": "string" + }, + "current_password": { + "description": "The user's current password.", + "type": "string" + }, + "password": { + "description": "The user's new password.", + "type": "string" + }, + "company_type": { + "description": "The company type.", + "type": "string" + }, + "company_name": { + "description": "The name of the company.", + "type": "string" + }, + "vat_number": { + "description": "The vat number of the user.", + "type": "string" + }, + "company_role": { + "description": "The role of the user in the company.", + "type": "string" + }, + "marketing": { + "description": "Flag if the user agreed to receive marketing communication.", + "type": "boolean" + }, + "ui_colorscheme": { + "description": "The user's chosen color scheme for user interfaces. Available values are 'light' and 'dark'.", + "type": "string" + }, + "default_catalog": { + "description": "The URL of a catalog file which overrides the default.", + "type": "string" + }, + "project_options_url": { + "description": "The URL of an account-wide project options file.", + "type": "string" + }, + "picture": { + "description": "Url of the user's picture.", + "type": "string" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "A User profile object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Profile" + } + } + } + } + }, + "x-property-id-kebab": "update-profile", + "x-tag-id-kebab": "User-Profiles", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Profile" + ], + "x-return-types-union": "\\Upsun\\Model\\Profile", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Profile" + }, + "x-returnable": true, + "x-description": [ + "Update a user profile, supplying one or more key/value pairs to to change." + ] + } + }, + "/profiles/{userId}/address": { + "get": { + "tags": [ + "User Profiles" + ], + "summary": "Get a user address", + "operationId": "get-address", + "parameters": [ + { + "$ref": "#/components/parameters/user_id" + } + ], + "responses": { + "200": { + "description": "A user Address object extended with field metadata", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/Address" + }, + { + "$ref": "#/components/schemas/AddressMetadata" + } + ] + } + } + } + } + }, + "x-property-id-kebab": "get-address", + "x-tag-id-kebab": "User-Profiles", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": {}, + "x-returnable": true + }, + "patch": { + "tags": [ + "User Profiles" + ], + "summary": "Update a user address", + "description": "Update a user address, supplying one or more key/value pairs to to change.", + "operationId": "update-address", + "parameters": [ + { + "$ref": "#/components/parameters/user_id" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Address" + } + } + } + }, + "responses": { + "200": { + "description": "A user Address object extended with field metadata.", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/Address" + }, + { + "$ref": "#/components/schemas/AddressMetadata" + } + ] + } + } + } + } + }, + "x-property-id-kebab": "update-address", + "x-tag-id-kebab": "User-Profiles", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": {}, + "x-returnable": true, + "x-description": [ + "Update a user address, supplying one or more key/value pairs to to change." + ] + } + }, + "/profile/{uuid}/picture": { + "post": { + "tags": [ + "User Profiles" + ], + "summary": "Create a user profile picture", + "operationId": "create-profile-picture", + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "The uuid of the user", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "properties": { + "file": { + "description": "The image file to upload.", + "type": "string", + "format": "binary" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "The new picture url.", + "content": { + "application/json": { + "schema": { + "properties": { + "url": { + "description": "The relative url of the picture.", + "type": "string" + } + }, + "type": "object" + } + } + } + } + }, + "x-property-id-kebab": "create-profile-picture", + "x-tag-id-kebab": "User-Profiles", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true + }, + "delete": { + "tags": [ + "User Profiles" + ], + "summary": "Delete a user profile picture", + "operationId": "delete-profile-picture", + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "The uuid of the user", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "204": { + "description": "No Content success." + } + }, + "x-property-id-kebab": "delete-profile-picture", + "x-tag-id-kebab": "User-Profiles", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false + } + }, + "/tickets": { + "get": { + "summary": "List support tickets", + "operationId": "list-tickets", + "parameters": [ + { + "$ref": "#/components/parameters/filter_ticket_id" + }, + { + "$ref": "#/components/parameters/filter_created" + }, + { + "$ref": "#/components/parameters/filter_updated" + }, + { + "$ref": "#/components/parameters/filter_type" + }, + { + "$ref": "#/components/parameters/filter_priority" + }, + { + "$ref": "#/components/parameters/filter_ticket_status" + }, + { + "$ref": "#/components/parameters/filter_requester_id" + }, + { + "$ref": "#/components/parameters/filter_submitter_id" + }, + { + "$ref": "#/components/parameters/filter_assignee_id" + }, + { + "$ref": "#/components/parameters/filter_has_incidents" + }, + { + "$ref": "#/components/parameters/filter_due" + }, + { + "name": "search", + "in": "query", + "description": "Search string for the ticket subject and description.", + "schema": { + "type": "string" + } + }, + { + "$ref": "#/components/parameters/page" + } + ], + "responses": { + "200": { + "description": "The list of tickets.", + "content": { + "application/json": { + "schema": { + "properties": { + "count": { + "description": "Total number of results.", + "type": "integer" + }, + "tickets": { + "description": "Array of support tickets.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ticket" + } + }, + "_links": { + "$ref": "#/components/schemas/HalLinks" + } + }, + "type": "object" + } + } + } + } + }, + "x-property-id-kebab": "list-tickets", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true + }, + "post": { + "tags": [ + "Support" + ], + "summary": "Create a new support ticket", + "operationId": "create-ticket", + "requestBody": { + "content": { + "application/json": { + "schema": { + "required": [ + "subject", + "description" + ], + "properties": { + "subject": { + "description": "A title of the ticket.", + "type": "string" + }, + "description": { + "description": "The description body of the support ticket.", + "type": "string" + }, + "requester_id": { + "description": "UUID of the ticket requester. Converted from the ZID value.", + "type": "string", + "format": "uuid" + }, + "priority": { + "description": "A priority of the ticket.", + "type": "string", + "enum": [ + "low", + "normal", + "high", + "urgent" + ] + }, + "subscription_id": { + "description": "see create()", + "type": "string" + }, + "organization_id": { + "description": "see create()", + "type": "string" + }, + "affected_url": { + "description": "see create().", + "type": "string", + "format": "url" + }, + "followup_tid": { + "description": "The unique ID of the ticket which this ticket is a follow-up to.", + "type": "string" + }, + "category": { + "description": "The category of the support ticket.", + "type": "string", + "enum": [ + "access", + "billing_question", + "complaint", + "compliance_question", + "configuration_change", + "general_question", + "incident_outage", + "bug_report", + "report_a_gui_bug", + "onboarding", + "close_my_account" + ] + }, + "attachments": { + "description": "A list of attachments for the ticket.", + "type": "array", + "items": { + "properties": { + "filename": { + "description": "The filename to be used in storage.", + "type": "string" + }, + "data": { + "description": "the base64 encoded file.", + "type": "string" + } + }, + "type": "object" + } + }, + "collaborator_ids": { + "description": "A list of collaborators uuids for the ticket.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "A Support Ticket object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ticket" + } + } + } + } + }, + "x-property-id-kebab": "create-ticket", + "x-tag-id-kebab": "Support", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Ticket" + ], + "x-return-types-union": "\\Upsun\\Model\\Ticket", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Ticket" + }, + "x-returnable": true + } + }, + "/tickets/{ticket_id}": { + "patch": { + "tags": [ + "Support" + ], + "summary": "Update a ticket", + "operationId": "update-ticket", + "parameters": [ + { + "name": "ticket_id", + "in": "path", + "description": "The ID of the ticket", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "status": { + "description": "The status of the support ticket.", + "type": "string", + "enum": [ + "open", + "solved" + ] + }, + "collaborator_ids": { + "description": "A list of collaborators uuids for the ticket.", + "type": "array", + "items": { + "type": "string" + } + }, + "collaborators_replace": { + "description": "Whether or not should replace ticket collaborators with the provided values. If false, the collaborators will be appended.", + "type": "boolean", + "default": null + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "Success.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ticket" + } + } + } + }, + "204": { + "description": "The ticket was not updated." + } + }, + "x-property-id-kebab": "update-ticket", + "x-tag-id-kebab": "Support", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Ticket", + "null" + ], + "x-return-types-union": "\\Upsun\\Model\\Ticket|null", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Ticket" + }, + "x-returnable": true + } + }, + "/tickets/priority": { + "get": { + "tags": [ + "Support" + ], + "summary": "List support ticket priorities", + "operationId": "list-ticket-priorities", + "parameters": [ + { + "name": "subscription_id", + "in": "query", + "description": "The ID of the subscription the ticket should be related to", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "category", + "in": "query", + "description": "The category of the support ticket.", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "An array of available priorities for that license.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "properties": { + "id": { + "description": "Machine name of the priority.", + "type": "string" + }, + "label": { + "description": "The human-readable label of the priority.", + "type": "string" + }, + "short_description": { + "description": "The short description of the priority.", + "type": "string" + }, + "description": { + "description": "The long description of the priority.", + "type": "string" + } + }, + "type": "object" + } + } + } + } + } + }, + "x-property-id-kebab": "list-ticket-priorities", + "x-tag-id-kebab": "Support", + "x-return-types-displayReturn": true, + "x-return-types": [ + "object[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "object[]" + }, + "x-returnable": true + } + }, + "/tickets/category": { + "get": { + "tags": [ + "Support" + ], + "summary": "List support ticket categories", + "operationId": "list-ticket-categories", + "parameters": [ + { + "name": "subscription_id", + "in": "query", + "description": "The ID of the subscription the ticket should be related to", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "organization_id", + "in": "query", + "description": "The ID of the organization the ticket should be related to", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "An array of available categories for a ticket.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "properties": { + "id": { + "description": "Machine name of the category as is listed in zendesk.", + "type": "string" + }, + "label": { + "description": "The human-readable label of the category.", + "type": "string" + } + }, + "type": "object" + } + } + } + } + } + }, + "x-property-id-kebab": "list-ticket-categories", + "x-tag-id-kebab": "Support", + "x-return-types-displayReturn": true, + "x-return-types": [ + "object[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "object[]" + }, + "x-returnable": true + } + }, + "/organizations/{organization_id}/invitations": { + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "post": { + "summary": "Invite user to an organization by email", + "description": "Creates an invitation to an organization for a user with the specified email address.", + "operationId": "create-org-invite", + "tags": [ + "Organization Invitations" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationInvitation" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "409": { + "description": "Conflict when there already is a pending invitation for the invitee", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "The email address of the invitee." + }, + "permissions": { + "$ref": "#/components/schemas/OrganizationPermissions" + }, + "force": { + "type": "boolean", + "description": "Whether to cancel any pending invitation for the specified invitee, and create a new invitation." + } + }, + "required": [ + "email", + "permissions" + ] + } + } + } + }, + "x-property-id-kebab": "create-org-invite", + "x-tag-id-kebab": "Organization-Invitations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationInvitation" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationInvitation", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationInvitation" + }, + "x-returnable": true, + "x-description": [ + "Creates an invitation to an organization for a user with the specified email address." + ] + }, + "get": { + "summary": "List invitations to an organization", + "description": "Returns a list of invitations to an organization.", + "operationId": "list-org-invites", + "tags": [ + "Organization Invitations" + ], + "parameters": [ + { + "in": "query", + "name": "filter[state]", + "description": "Allows filtering by `state` of the invtations: \"pending\" (default), \"error\".", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "page[size]", + "description": "Determines the number of items to show.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": null + } + }, + { + "in": "query", + "name": "page[before]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page[after]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.\n", + "schema": { + "type": "string", + "enum": [ + "updated_at", + "-updated_at" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrganizationInvitation" + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-org-invites", + "x-tag-id-kebab": "Organization-Invitations", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationInvitation[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationInvitation[]" + }, + "x-returnable": true, + "x-description": [ + "Returns a list of invitations to an organization." + ] + } + }, + "/organizations/{organization_id}/invitations/{invitation_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/InvitationID" + } + ], + "delete": { + "summary": "Cancel a pending invitation to an organization", + "description": "Cancels the specified invitation.", + "operationId": "cancel-org-invite", + "tags": [ + "Organization Invitations" + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "cancel-org-invite", + "x-tag-id-kebab": "Organization-Invitations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Cancels the specified invitation." + ] + } + }, + "/projects/{project_id}/invitations": { + "parameters": [ + { + "$ref": "#/components/parameters/ProjectID" + } + ], + "post": { + "summary": "Invite user to a project by email", + "description": "Creates an invitation to a project for a user with the specified email address.", + "operationId": "create-project-invite", + "tags": [ + "Project Invitations" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectInvitation" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "402": { + "description": "Payment Required when the number of users exceeds the subscription limit", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "409": { + "description": "Conflict when there already is a pending invitation for the invitee", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "role": { + "type": "string", + "enum": [ + "admin", + "viewer" + ], + "description": "The role the invitee should be given on the project.", + "default": null + }, + "email": { + "type": "string", + "format": "email", + "description": "The email address of the invitee." + }, + "permissions": { + "type": "array", + "description": "Specifying the role on each environment type.", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "production", + "staging", + "development" + ], + "description": "The environment type." + }, + "role": { + "type": "string", + "enum": [ + "admin", + "viewer", + "contributor" + ], + "description": "The role the invitee should be given on the environment type." + } + } + } + }, + "environments": { + "deprecated": true, + "type": "array", + "description": "(Deprecated, use permissions instead) Specifying the role on each environment.", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The ID of the environment." + }, + "role": { + "type": "string", + "enum": [ + "admin", + "viewer", + "contributor" + ], + "description": "The role the invitee should be given on the environment." + } + } + } + }, + "force": { + "type": "boolean", + "description": "Whether to cancel any pending invitation for the specified invitee, and create a new invitation." + } + }, + "required": [ + "email" + ] + } + } + } + }, + "x-property-id-kebab": "create-project-invite", + "x-tag-id-kebab": "Project-Invitations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\ProjectInvitation" + ], + "x-return-types-union": "\\Upsun\\Model\\ProjectInvitation", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ProjectInvitation" + }, + "x-returnable": true, + "x-description": [ + "Creates an invitation to a project for a user with the specified email address." + ] + }, + "get": { + "summary": "List invitations to a project", + "description": "Returns a list of invitations to a project.", + "operationId": "list-project-invites", + "tags": [ + "Project Invitations" + ], + "parameters": [ + { + "in": "query", + "name": "filter[state]", + "description": "Allows filtering by `state` of the invtations: \"pending\" (default), \"error\".", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "page[size]", + "description": "Determines the number of items to show.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": null + } + }, + { + "in": "query", + "name": "page[before]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page[after]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.\n", + "schema": { + "type": "string", + "enum": [ + "updated_at", + "-updated_at" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectInvitation" + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-project-invites", + "x-tag-id-kebab": "Project-Invitations", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\ProjectInvitation[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ProjectInvitation[]" + }, + "x-returnable": true, + "x-description": [ + "Returns a list of invitations to a project." + ] + } + }, + "/projects/{project_id}/invitations/{invitation_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/ProjectID" + }, + { + "$ref": "#/components/parameters/InvitationID" + } + ], + "delete": { + "summary": "Cancel a pending invitation to a project", + "description": "Cancels the specified invitation.", + "operationId": "cancel-project-invite", + "tags": [ + "Project Invitations" + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "cancel-project-invite", + "x-tag-id-kebab": "Project-Invitations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Cancels the specified invitation." + ] + } + }, + "/ref/users": { + "get": { + "summary": "List referenced users", + "description": "Retrieves a list of users referenced by a trusted service. Clients cannot construct the URL themselves. The correct URL will be provided in the HAL links of another API response, in the _links object with a key like ref:users:0.", + "operationId": "list-referenced-users", + "tags": [ + "References" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "A map of referenced users indexed by the user ID.", + "additionalProperties": { + "$ref": "#/components/schemas/UserReference" + } + }, + "examples": { + "example-1": { + "value": { + "497f6eca-6276-4993-bfeb-53cbbbba6f08": { + "email": "user@example.com", + "first_name": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_name": "string", + "picture": "https://accounts.platform.sh/profiles/blimp_profile/themes/platformsh_theme/images/mail/logo.png", + "username": "string", + "mfa_enabled": false, + "sso_enabled": false + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "parameters": [ + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "in", + "description": "The list of comma-separated user IDs generated by a trusted service.", + "required": true + }, + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "sig", + "description": "The signature of this request generated by a trusted service.", + "required": true + } + ], + "x-property-id-kebab": "list-referenced-users", + "x-tag-id-kebab": "References", + "x-return-types-displayReturn": true, + "x-return-types": [ + "array" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "array" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of users referenced by a trusted service. Clients cannot construct the URL themselves. The", + "correct URL will be provided in the HAL links of another API response, in the _links object with a", + "key like ref:users:0." + ] + } + }, + "/ref/teams": { + "get": { + "summary": "List referenced teams", + "description": "Retrieves a list of teams referenced by a trusted service. Clients cannot construct the URL themselves. The correct URL will be provided in the HAL links of another API response, in the _links object with a key like ref:teams:0.", + "operationId": "list-referenced-teams", + "tags": [ + "References" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "A map of referenced teams indexed by the team ID.", + "additionalProperties": { + "$ref": "#/components/schemas/TeamReference" + } + }, + "examples": { + "example-1": { + "value": { + "01FVMKN9KHVWWVY488AVKDWHR3": { + "id": "01FVMKN9KHVWWVY488AVKDWHR3", + "label": "Contractors" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "parameters": [ + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "in", + "description": "The list of comma-separated team IDs generated by a trusted service.", + "required": true + }, + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "sig", + "description": "The signature of this request generated by a trusted service.", + "required": true + } + ], + "x-property-id-kebab": "list-referenced-teams", + "x-tag-id-kebab": "References", + "x-return-types-displayReturn": true, + "x-return-types": [ + "array" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "array" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of teams referenced by a trusted service. Clients cannot construct the URL themselves. The", + "correct URL will be provided in the HAL links of another API response, in the _links object with a", + "key like ref:teams:0." + ] + } + }, + "/teams": { + "get": { + "summary": "List teams", + "description": "Retrieves a list of teams.", + "operationId": "list-teams", + "tags": [ + "Teams" + ], + "parameters": [ + { + "in": "query", + "name": "filter[organization_id]", + "description": "Allows filtering by `organization_id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[id]", + "description": "Allows filtering by `id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[updated_at]", + "description": "Allows filtering by `updated_at` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/DateTimeFilter" + } + }, + { + "in": "query", + "name": "page[size]", + "description": "Determines the number of items to show.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": null + } + }, + { + "in": "query", + "name": "page[before]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page[after]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.\n", + "schema": { + "type": "string", + "enum": [ + "label", + "-label", + "created_at", + "-created_at", + "updated_at", + "-updated_at" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Team" + } + }, + "count": { + "type": "integer", + "description": "Total count of all the teams." + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-teams", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of teams." + ] + }, + "post": { + "summary": "Create team", + "description": "Creates a new team.", + "operationId": "create-team", + "tags": [ + "Teams" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "organization_id", + "label" + ], + "properties": { + "organization_id": { + "type": "string", + "format": "ulid", + "description": "The ID of the parent organization." + }, + "label": { + "type": "string", + "description": "The human-readable label of the team." + }, + "project_permissions": { + "type": "array", + "description": "Project permissions that are granted to the team.", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Team" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "create-team", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Team" + ], + "x-return-types-union": "\\Upsun\\Model\\Team", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Team" + }, + "x-returnable": true, + "x-description": [ + "Creates a new team." + ] + } + }, + "/teams/{team_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamID" + } + ], + "get": { + "summary": "Get team", + "description": "Retrieves the specified team.", + "operationId": "get-team", + "tags": [ + "Teams" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Team" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-team", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Team" + ], + "x-return-types-union": "\\Upsun\\Model\\Team", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Team" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the specified team." + ] + }, + "patch": { + "summary": "Update team", + "description": "Updates the specified team.", + "operationId": "update-team", + "tags": [ + "Teams" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "label": { + "type": "string", + "description": "The human-readable label of the team." + }, + "project_permissions": { + "type": "array", + "description": "Project permissions that are granted to the team.", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Team" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "update-team", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Team" + ], + "x-return-types-union": "\\Upsun\\Model\\Team", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Team" + }, + "x-returnable": true, + "x-description": [ + "Updates the specified team." + ] + }, + "delete": { + "summary": "Delete team", + "description": "Deletes the specified team.", + "operationId": "delete-team", + "tags": [ + "Teams" + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "delete-team", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Deletes the specified team." + ] + } + }, + "/teams/{team_id}/members": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamID" + } + ], + "get": { + "summary": "List team members", + "description": "Retrieves a list of users associated with a single team.", + "operationId": "list-team-members", + "tags": [ + "Teams" + ], + "parameters": [ + { + "in": "query", + "name": "page[before]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page[after]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.\n", + "schema": { + "type": "string", + "enum": [ + "created_at", + "-created_at", + "updated_at", + "-updated_at" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TeamMember" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-team-members", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of users associated with a single team." + ] + }, + "post": { + "summary": "Create team member", + "description": "Creates a new team member.", + "operationId": "create-team-member", + "tags": [ + "Teams" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "user_id" + ], + "properties": { + "user_id": { + "type": "string", + "format": "uuid", + "description": "ID of the user." + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TeamMember" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "create-team-member", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\TeamMember" + ], + "x-return-types-union": "\\Upsun\\Model\\TeamMember", + "x-phpdoc": { + "return": "\\Upsun\\Model\\TeamMember" + }, + "x-returnable": true, + "x-description": [ + "Creates a new team member." + ] + } + }, + "/teams/{team_id}/members/{user_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamID" + }, + { + "$ref": "#/components/parameters/UserID" + } + ], + "get": { + "summary": "Get team member", + "description": "Retrieves the specified team member.", + "operationId": "get-team-member", + "tags": [ + "Teams" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TeamMember" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-team-member", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\TeamMember" + ], + "x-return-types-union": "\\Upsun\\Model\\TeamMember", + "x-phpdoc": { + "return": "\\Upsun\\Model\\TeamMember" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the specified team member." + ] + }, + "delete": { + "summary": "Delete team member", + "description": "Deletes the specified team member.", + "operationId": "delete-team-member", + "tags": [ + "Teams" + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "delete-team-member", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Deletes the specified team member." + ] + } + }, + "/users/{user_id}/extended-access": { + "get": { + "summary": "List extended access of a user", + "description": "List extended access of the given user, which includes both individual and team access to project and organization.", + "operationId": "list-user-extended-access", + "tags": [ + "Grants" + ], + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + }, + { + "in": "query", + "name": "filter[resource_type]", + "description": "Allows filtering by `resource_type` (project or organization) using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[organization_id]", + "description": "Allows filtering by `organization_id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[permissions]", + "description": "Allows filtering by `permissions` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "x-examples": { + "example-1": { + "user_id": "ff9c8376-0227-4928-9b52-b08bc5426689", + "resource_id": "an3sjsfwfbgkm", + "resource_type": "project", + "organization_id": "01H2X80DMRDZWR6CX753YQHTND", + "granted_at": "2022-04-01T10:11:30.783289Z", + "updated_at": "2022-04-03T22:12:59.937864Z", + "permissions": [ + "viewer", + "staging:contributor" + ] + } + }, + "properties": { + "user_id": { + "type": "string", + "format": "uuid", + "description": "The ID of the user." + }, + "resource_id": { + "type": "string", + "description": "The ID of the resource." + }, + "resource_type": { + "type": "string", + "description": "The type of the resource access to which is granted.", + "enum": [ + "project", + "organization" + ] + }, + "organization_id": { + "type": "string", + "description": "The ID of the organization owning the resource." + }, + "permissions": { + "type": "array", + "description": "List of project permissions.", + "items": { + "type": "string" + } + }, + "granted_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the access was granted." + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the access was updated." + } + } + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-user-extended-access", + "x-tag-id-kebab": "Grants", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "List extended access of the given user, which includes both individual and team access to project and", + "organization." + ] + } + }, + "/users/me": { + "get": { + "summary": "Get the current user", + "description": "Retrieves the current user, determined from the used access token.", + "operationId": "get-current-user", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "get-current-user", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\User" + ], + "x-return-types-union": "\\Upsun\\Model\\User", + "x-phpdoc": { + "return": "\\Upsun\\Model\\User" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the current user, determined from the used access token." + ] + } + }, + "/users/email={email}": { + "parameters": [ + { + "schema": { + "type": "string", + "format": "email", + "example": "hello@example.com" + }, + "name": "email", + "in": "path", + "required": true, + "description": "The user's email address." + } + ], + "get": { + "summary": "Get a user by email", + "description": "Retrieves a user matching the specified email address.", + "operationId": "get-user-by-email-address", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "get-user-by-email-address", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\User" + ], + "x-return-types-union": "\\Upsun\\Model\\User", + "x-phpdoc": { + "return": "\\Upsun\\Model\\User" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a user matching the specified email address." + ] + } + }, + "/users/username={username}": { + "parameters": [ + { + "schema": { + "type": "string", + "example": "platform-sh" + }, + "name": "username", + "in": "path", + "required": true, + "description": "The user's username." + } + ], + "get": { + "summary": "Get a user by username", + "description": "Retrieves a user matching the specified username.", + "operationId": "get-user-by-username", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + }, + "examples": {} + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "get-user-by-username", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\User" + ], + "x-return-types-union": "\\Upsun\\Model\\User", + "x-phpdoc": { + "return": "\\Upsun\\Model\\User" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a user matching the specified username." + ] + } + }, + "/users/{user_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "get": { + "summary": "Get a user", + "description": "Retrieves the specified user.", + "operationId": "get-user", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "get-user", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\User" + ], + "x-return-types-union": "\\Upsun\\Model\\User", + "x-phpdoc": { + "return": "\\Upsun\\Model\\User" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the specified user." + ] + }, + "patch": { + "summary": "Update a user", + "description": "Updates the specified user.", + "operationId": "update-user", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "", + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "The user's username." + }, + "first_name": { + "type": "string", + "description": "The user's first name." + }, + "last_name": { + "type": "string", + "description": "The user's last name." + }, + "picture": { + "type": "string", + "format": "uri", + "description": "The user's picture." + }, + "company": { + "type": "string", + "description": "The user's company." + }, + "website": { + "type": "string", + "format": "uri", + "description": "The user's website." + }, + "country": { + "type": "string", + "maxLength": 2, + "minLength": 2, + "description": "The user's country (2-letter country code)." + } + }, + "x-examples": { + "example-1": { + "company": "Platform.sh SAS", + "country": "EU", + "first_name": "Hello", + "last_name": "World", + "picture": "https://accounts.platform.sh/profiles/blimp_profile/themes/platformsh_theme/images/mail/logo.png", + "username": "username", + "website": "https://platform.sh" + } + } + } + } + } + }, + "x-property-id-kebab": "update-user", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\User" + ], + "x-return-types-union": "\\Upsun\\Model\\User", + "x-phpdoc": { + "return": "\\Upsun\\Model\\User" + }, + "x-returnable": true, + "x-description": [ + "Updates the specified user." + ] + } + }, + "/users/{user_id}/emailaddress": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "post": { + "summary": "Reset email address", + "description": "Requests a reset of the user's email address. A confirmation email will be sent to the new address when the request is accepted.", + "operationId": "reset-email-address", + "tags": [ + "Users" + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "email_address": { + "type": "string", + "format": "email" + } + }, + "required": [ + "email_address" + ] + } + } + }, + "description": "" + }, + "x-property-id-kebab": "reset-email-address", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Requests a reset of the user's email address. A confirmation email will be sent to the new address when the", + "request is accepted." + ] + } + }, + "/users/{user_id}/resetpassword": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "post": { + "summary": "Reset user password", + "description": "Requests a reset of the user's password. A password reset email will be sent to the user when the request is accepted.", + "operationId": "reset-password", + "tags": [ + "Users" + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "reset-password", + "x-tag-id-kebab": "Users", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Requests a reset of the user's password. A password reset email will be sent to the user when the request is", + "accepted." + ] + } + }, + "/users/{user_id}/api-tokens": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "get": { + "summary": "List a user's API tokens", + "description": "Retrieves a list of API tokens associated with a single user.", + "operationId": "list-api-tokens", + "tags": [ + "Api Tokens" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApiToken" + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-api-tokens", + "x-tag-id-kebab": "Api-Tokens", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\ApiToken[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ApiToken[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of API tokens associated with a single user." + ] + }, + "post": { + "summary": "Create an API token", + "description": "Creates an API token", + "operationId": "create-api-token", + "tags": [ + "Api Tokens" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiToken" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The token name." + } + }, + "required": [ + "name" + ] + } + } + } + }, + "x-property-id-kebab": "create-api-token", + "x-tag-id-kebab": "Api-Tokens", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\ApiToken" + ], + "x-return-types-union": "\\Upsun\\Model\\ApiToken", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ApiToken" + }, + "x-returnable": true, + "x-description": [ + "Creates an API token" + ] + } + }, + "/users/{user_id}/api-tokens/{token_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + }, + { + "schema": { + "type": "string", + "format": "uuid" + }, + "name": "token_id", + "in": "path", + "required": true, + "description": "The ID of the token." + } + ], + "get": { + "summary": "Get an API token", + "description": "Retrieves the specified API token.", + "operationId": "get-api-token", + "tags": [ + "Api Tokens" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiToken" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "get-api-token", + "x-tag-id-kebab": "Api-Tokens", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\ApiToken" + ], + "x-return-types-union": "\\Upsun\\Model\\ApiToken", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ApiToken" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the specified API token." + ] + }, + "delete": { + "summary": "Delete an API token", + "description": "Deletes an API token", + "operationId": "delete-api-token", + "tags": [ + "Api Tokens" + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "delete-api-token", + "x-tag-id-kebab": "Api-Tokens", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Deletes an API token" + ] + } + }, + "/users/{user_id}/connections": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "get": { + "summary": "List federated login connections", + "description": "Retrieves a list of connections associated with a single user.", + "operationId": "list-login-connections", + "tags": [ + "Connections" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Connection" + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-login-connections", + "x-tag-id-kebab": "Connections", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Connection[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Connection[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of connections associated with a single user." + ] + } + }, + "/users/{user_id}/connections/{provider}": { + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "provider", + "in": "path", + "required": true, + "description": "The name of the federation provider." + }, + { + "$ref": "#/components/parameters/UserID" + } + ], + "get": { + "summary": "Get a federated login connection", + "description": "Retrieves the specified connection.", + "operationId": "get-login-connection", + "tags": [ + "Connections" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Connection" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "get-login-connection", + "x-tag-id-kebab": "Connections", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Connection" + ], + "x-return-types-union": "\\Upsun\\Model\\Connection", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Connection" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the specified connection." + ] + }, + "delete": { + "summary": "Delete a federated login connection", + "description": "Deletes the specified connection.", + "operationId": "delete-login-connection", + "tags": [ + "Connections" + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "delete-login-connection", + "x-tag-id-kebab": "Connections", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Deletes the specified connection." + ] + } + }, + "/users/{user_id}/totp": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "get": { + "summary": "Get information about TOTP enrollment", + "description": "Retrieves TOTP enrollment information.", + "operationId": "get-totp-enrollment", + "tags": [ + "Mfa" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "issuer": { + "type": "string", + "format": "uri", + "description": "" + }, + "account_name": { + "type": "string", + "description": "Account name for the enrollment." + }, + "secret": { + "type": "string", + "description": "The secret seed for the enrollment" + }, + "qr_code": { + "type": "string", + "format": "byte", + "description": "Data URI of a PNG QR code image for the enrollment." + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "409": { + "description": "Conflict" + } + }, + "x-property-id-kebab": "get-totp-enrollment", + "x-tag-id-kebab": "Mfa", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves TOTP enrollment information." + ] + }, + "post": { + "summary": "Confirm TOTP enrollment", + "description": "Confirms the given TOTP enrollment.", + "operationId": "confirm-totp-enrollment", + "tags": [ + "Mfa" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "recovery_codes": { + "type": "array", + "description": "A list of recovery codes for the MFA enrollment.", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "secret": { + "type": "string", + "description": "The secret seed for the enrollment" + }, + "passcode": { + "type": "string", + "description": "TOTP passcode for the enrollment" + } + }, + "required": [ + "secret", + "passcode" + ] + } + } + }, + "description": "" + }, + "x-property-id-kebab": "confirm-totp-enrollment", + "x-tag-id-kebab": "Mfa", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Confirms the given TOTP enrollment." + ] + }, + "delete": { + "summary": "Withdraw TOTP enrollment", + "description": "Withdraws from the TOTP enrollment.", + "operationId": "withdraw-totp-enrollment", + "tags": [ + "Mfa" + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "withdraw-totp-enrollment", + "x-tag-id-kebab": "Mfa", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Withdraws from the TOTP enrollment." + ] + } + }, + "/users/{user_id}/codes": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "post": { + "summary": "Re-create recovery codes", + "description": "Re-creates recovery codes for the MFA enrollment.", + "operationId": "recreate-recovery-codes", + "tags": [ + "Mfa" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "recovery_codes": { + "type": "array", + "description": "A list of recovery codes for the MFA enrollment.", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found" + } + }, + "x-property-id-kebab": "recreate-recovery-codes", + "x-tag-id-kebab": "Mfa", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Re-creates recovery codes for the MFA enrollment." + ] + } + }, + "/users/{user_id}/phonenumber": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "post": { + "summary": "Verify phone number", + "description": "Starts a phone number verification session.", + "operationId": "verify-phone-number", + "tags": [ + "PhoneNumber" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "sid": { + "type": "string", + "description": "Session ID of the verification." + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "channel": { + "type": "string", + "description": "The channel used to receive the verification code.", + "enum": [ + "sms", + "whatsapp", + "call" + ] + }, + "phone_number": { + "type": "string", + "description": "The phone number used to receive the verification code." + } + }, + "required": [ + "channel", + "phone_number" + ] + } + } + } + }, + "x-property-id-kebab": "verify-phone-number", + "x-tag-id-kebab": "PhoneNumber", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Starts a phone number verification session." + ] + } + }, + "/users/{user_id}/phonenumber/{sid}": { + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "sid", + "in": "path", + "required": true, + "description": "The session ID obtained from `POST /users/{user_id}/phonenumber`." + }, + { + "$ref": "#/components/parameters/UserID" + } + ], + "post": { + "summary": "Confirm phone number", + "description": "Confirms phone number using a verification code.", + "operationId": "confirm-phone-number", + "tags": [ + "PhoneNumber" + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "The verification code received on your phone." + } + }, + "required": [ + "code" + ] + } + } + } + }, + "x-property-id-kebab": "confirm-phone-number", + "x-tag-id-kebab": "PhoneNumber", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Confirms phone number using a verification code." + ] + } + }, + "/users/{user_id}/teams": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "get": { + "summary": "User teams", + "description": "Retrieves teams that the specified user is a member of.", + "operationId": "list-user-teams", + "tags": [ + "Teams" + ], + "parameters": [ + { + "in": "query", + "name": "filter[organization_id]", + "description": "Allows filtering by `organization_id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[updated_at]", + "description": "Allows filtering by `updated_at` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/DateTimeFilter" + } + }, + { + "in": "query", + "name": "page[size]", + "description": "Determines the number of items to show.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": null + } + }, + { + "in": "query", + "name": "page[before]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page[after]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.\n", + "schema": { + "type": "string", + "enum": [ + "created_at", + "-created_at", + "updated_at", + "-updated_at" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Team" + } + }, + "count": { + "type": "integer", + "description": "Total count of all the teams." + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-user-teams", + "x-tag-id-kebab": "Teams", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves teams that the specified user is a member of." + ] + } + }, + "/projects/{projectId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "get-projects", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Project" + } + } + } + } + }, + "tags": [ + "Project" + ], + "summary": "Get a project", + "description": "Retrieve the details of a single project.", + "x-property-id-kebab": "get-projects", + "x-tag-id-kebab": "Project", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Project" + ], + "x-return-types-union": "\\Upsun\\Model\\Project", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Project" + }, + "x-returnable": true, + "x-description": [ + "Retrieve the details of a single project." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectPatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "update-projects", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Project" + ], + "summary": "Update a project", + "description": "Update the details of an existing project.", + "x-property-id-kebab": "update-projects", + "x-tag-id-kebab": "Project", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update the details of an existing project." + ] + } + }, + "/projects/{projectId}/activities": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-activities", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActivityCollection" + } + } + } + } + }, + "tags": [ + "Project Activity" + ], + "summary": "Get project activity log", + "description": "Retrieve a project's activity log including logging actions in all\nenvironments within a project. This returns a list of objects\nwith records of actions such as:\n\n- Commits being pushed to the repository\n- A new environment being branched out from the specified environment\n- A snapshot being created of the specified environment\n\nThe object includes a timestamp of when the action occurred\n(`created_at`), when the action concluded (`updated_at`),\nthe current `state` of the action, the action's completion\npercentage (`completion_percent`), the `environments` it\napplies to and when the activity expires (`expires_at`).\n\nThere are other related information in the `payload`.\nThe contents of the `payload` varies based on the `type` of the\nactivity. For example:\n\n- An `environment.branch` action's `payload` can contain objects\nrepresenting the environment's `parent` environment and the\nbranching action's `outcome`.\n\n- An `environment.push` action's `payload` can contain objects\nrepresenting the `environment`, the specific `commits` included in\nthe push, and the `user` who pushed.\n\nExpired activities are removed from the project activity log, except\nthe last 100 expired objects provided they are not of type `environment.cron`\nor `environment.backup`.\n", + "x-property-id-kebab": "list-projects-activities", + "x-tag-id-kebab": "Project-Activity", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Activity[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Activity[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a project's activity log including logging actions in all environments within a project. This returns a", + "list of objects with records of actions such as: - Commits being pushed to the repository - A new environment", + "being branched out from the specified environment - A snapshot being created of the specified environment The", + "object includes a timestamp of when the action occurred (`created_at`), when the action concluded (`updated_at`),", + "the current `state` of the action, the action's completion percentage (`completion_percent`), the `environments`", + "it applies to and when the activity expires (`expires_at`). There are other related information in the `payload`.", + "The contents of the `payload` varies based on the `type` of the activity. For example: - An `environment.branch`", + "action's `payload` can contain objects representing the environment's `parent` environment and the branching", + "action's `outcome`. - An `environment.push` action's `payload` can contain objects representing the", + "`environment`, the specific `commits` included in the push, and the `user` who pushed. Expired activities are", + "removed from the project activity log, except the last 100 expired objects provided they are not of type", + "`environment.cron` or `environment.backup`." + ] + } + }, + "/projects/{projectId}/activities/{activityId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "activityId" + } + ], + "operationId": "get-projects-activities", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Activity" + } + } + } + } + }, + "tags": [ + "Project Activity" + ], + "summary": "Get a project activity log entry", + "description": "Retrieve a single activity log entry as specified by an\n`id` returned by the\n[Get project activity log](#tag/Project-Activity%2Fpaths%2F~1projects~1%7BprojectId%7D~1activities%2Fget)\nendpoint. See the documentation on that endpoint for details about\nthe information this endpoint can return.\n", + "x-property-id-kebab": "get-projects-activities", + "x-tag-id-kebab": "Project-Activity", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Activity" + ], + "x-return-types-union": "\\Upsun\\Model\\Activity", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Activity" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a single activity log entry as specified by an `id` returned by the Get project activity log", + "(https://docs.upsun.com/api/#tag/Project-Activity/paths//projects/{projectId}/activities/get) endpoint. See the", + "documentation on that endpoint for details about the information this endpoint can return." + ] + } + }, + "/projects/{projectId}/activities/{activityId}/cancel": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "activityId" + } + ], + "operationId": "action-projects-activities-cancel", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Project Activity" + ], + "summary": "Cancel a project activity", + "description": "Cancel a single activity as specified by an `id` returned by the\n[Get project activity log](#tag/Project-Activity%2Fpaths%2F~1projects~1%7BprojectId%7D~1activities%2Fget)\nendpoint.\n\nPlease note that not all activities are cancelable.\n", + "x-property-id-kebab": "action-projects-activities-cancel", + "x-tag-id-kebab": "Project-Activity", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Cancel a single activity as specified by an `id` returned by the Get project activity log", + "(https://docs.upsun.com/api/#tag/Project-Activity/paths//projects/{projectId}/activities/get) endpoint. Please", + "note that not all activities are cancelable." + ] + } + }, + "/projects/{projectId}/capabilities": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "get-projects-capabilities", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectCapabilities" + } + } + } + } + }, + "tags": [ + "Project" + ], + "summary": "Get a project's capabilities", + "description": "Get a list of capabilities on a project, as defined by the billing system.\nFor instance, one special capability that could be defined on a project is\nlarge development environments.\n", + "x-property-id-kebab": "get-projects-capabilities", + "x-tag-id-kebab": "Project", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\ProjectCapabilities" + ], + "x-return-types-union": "\\Upsun\\Model\\ProjectCapabilities", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ProjectCapabilities" + }, + "x-returnable": true, + "x-description": [ + "Get a list of capabilities on a project, as defined by the billing system. For instance, one special capability", + "that could be defined on a project is large development environments." + ] + } + }, + "/projects/{projectId}/certificates": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-certificates", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CertificateCollection" + } + } + } + } + }, + "tags": [ + "Cert Management" + ], + "summary": "Get list of SSL certificates", + "description": "Retrieve a list of objects representing the SSL certificates\nassociated with a project.\n", + "x-property-id-kebab": "list-projects-certificates", + "x-tag-id-kebab": "Cert-Management", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Certificate[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Certificate[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a list of objects representing the SSL certificates associated with a project." + ] + }, + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "create-projects-certificates", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CertificateCreateInput" + } + } + } + }, + "tags": [ + "Cert Management" + ], + "summary": "Add an SSL certificate", + "description": "Add a single SSL certificate to a project.\n", + "x-property-id-kebab": "create-projects-certificates", + "x-tag-id-kebab": "Cert-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Add a single SSL certificate to a project." + ] + } + }, + "/projects/{projectId}/certificates/{certificateId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "certificateId" + } + ], + "operationId": "get-projects-certificates", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Certificate" + } + } + } + } + }, + "tags": [ + "Cert Management" + ], + "summary": "Get an SSL certificate", + "description": "Retrieve information about a single SSL certificate\nassociated with a project.\n", + "x-property-id-kebab": "get-projects-certificates", + "x-tag-id-kebab": "Cert-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Certificate" + ], + "x-return-types-union": "\\Upsun\\Model\\Certificate", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Certificate" + }, + "x-returnable": true, + "x-description": [ + "Retrieve information about a single SSL certificate associated with a project." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CertificatePatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "certificateId" + } + ], + "operationId": "update-projects-certificates", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Cert Management" + ], + "summary": "Update an SSL certificate", + "description": "Update a single SSL certificate associated with a project.\n", + "x-property-id-kebab": "update-projects-certificates", + "x-tag-id-kebab": "Cert-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update a single SSL certificate associated with a project." + ] + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "certificateId" + } + ], + "operationId": "delete-projects-certificates", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Cert Management" + ], + "summary": "Delete an SSL certificate", + "description": "Delete a single SSL certificate associated with a project.\n", + "x-property-id-kebab": "delete-projects-certificates", + "x-tag-id-kebab": "Cert-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Delete a single SSL certificate associated with a project." + ] + } + }, + "/projects/{projectId}/clear_build_cache": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "action-projects-clear-build-cache", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Project" + ], + "summary": "Clear project build cache", + "description": "On rare occasions, a project's build cache can become corrupted. This\nendpoint will entirely flush the project's build cache. More information\non [clearing the build cache can be found in our user documentation.](https://docs.upsun.com/anchors/troubleshoot/clear-build-cache/)\n", + "x-property-id-kebab": "action-projects-clear-build-cache", + "x-tag-id-kebab": "Project", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "On rare occasions, a project's build cache can become corrupted. This endpoint will entirely flush the project's", + "build cache. More information on [clearing the build cache can be found in our user", + "documentation.](https://docs.upsun.com/anchors/troubleshoot/clear-build-cache/)" + ] + } + }, + "/projects/{projectId}/deployments": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-deployments", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeploymentTargetCollection" + } + } + } + } + }, + "tags": [ + "Deployment Target" + ], + "summary": "Get project deployment target info", + "description": "The deployment target information for the project.\n", + "x-property-id-kebab": "list-projects-deployments", + "x-tag-id-kebab": "Deployment-Target", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\DeploymentTarget[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\DeploymentTarget[]" + }, + "x-returnable": true, + "x-description": [ + "The deployment target information for the project." + ] + }, + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "create-projects-deployments", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeploymentTargetCreateInput" + } + } + } + }, + "tags": [ + "Deployment Target" + ], + "summary": "Create a project deployment target", + "description": "Set the deployment target information for a project.\n", + "x-property-id-kebab": "create-projects-deployments", + "x-tag-id-kebab": "Deployment-Target", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Set the deployment target information for a project." + ] + } + }, + "/projects/{projectId}/deployments/{deploymentTargetConfigurationId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "deploymentTargetConfigurationId" + } + ], + "operationId": "get-projects-deployments", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeploymentTarget" + } + } + } + } + }, + "tags": [ + "Deployment Target" + ], + "summary": "Get a single project deployment target", + "description": "Get a single deployment target configuration of a project.\n", + "x-property-id-kebab": "get-projects-deployments", + "x-tag-id-kebab": "Deployment-Target", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\DeploymentTarget" + ], + "x-return-types-union": "\\Upsun\\Model\\DeploymentTarget", + "x-phpdoc": { + "return": "\\Upsun\\Model\\DeploymentTarget" + }, + "x-returnable": true, + "x-description": [ + "Get a single deployment target configuration of a project." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeploymentTargetPatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "deploymentTargetConfigurationId" + } + ], + "operationId": "update-projects-deployments", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Deployment Target" + ], + "summary": "Update a project deployment", + "x-property-id-kebab": "update-projects-deployments", + "x-tag-id-kebab": "Deployment-Target", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "deploymentTargetConfigurationId" + } + ], + "operationId": "delete-projects-deployments", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Deployment Target" + ], + "summary": "Delete a single project deployment target", + "description": "Delete a single deployment target configuration associated with a specific project.\n", + "x-property-id-kebab": "delete-projects-deployments", + "x-tag-id-kebab": "Deployment-Target", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Delete a single deployment target configuration associated with a specific project." + ] + } + }, + "/projects/{projectId}/domains": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DomainCollection" + } + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Get list of project domains", + "description": "Retrieve a list of objects representing the user-specified domains\nassociated with a project. Note that this does *not* return the\ndomains automatically assigned to a project that appear under\n\"Access site\" on the user interface.\n", + "x-property-id-kebab": "list-projects-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Domain[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Domain[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a list of objects representing the user-specified domains associated with a project. Note that this does", + "*not* return the domains automatically assigned to a project that appear under \"Access site\" on the user", + "interface." + ] + }, + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "create-projects-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DomainCreateInput" + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Add a project domain", + "description": "Add a single domain to a project.\nIf the `ssl` field is left blank without an object containing\na PEM-encoded SSL certificate, a certificate will\n[be provisioned for you via Let's Encrypt.](https://docs.upsun.com/anchors/routes/https/certificates/)\n", + "x-property-id-kebab": "create-projects-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Add a single domain to a project. If the `ssl` field is left blank without an object containing a PEM-encoded SSL", + "certificate, a certificate will [be provisioned for you via Let's", + "Encrypt.](https://docs.upsun.com/anchors/routes/https/certificates/)" + ] + } + }, + "/projects/{projectId}/domains/{domainId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "domainId" + } + ], + "operationId": "get-projects-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Domain" + } + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Get a project domain", + "description": "Retrieve information about a single user-specified domain\nassociated with a project.\n", + "x-property-id-kebab": "get-projects-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Domain" + ], + "x-return-types-union": "\\Upsun\\Model\\Domain", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Domain" + }, + "x-returnable": true, + "x-description": [ + "Retrieve information about a single user-specified domain associated with a project." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DomainPatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "domainId" + } + ], + "operationId": "update-projects-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Update a project domain", + "description": "Update the information associated with a single user-specified\ndomain associated with a project.\n", + "x-property-id-kebab": "update-projects-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update the information associated with a single user-specified domain associated with a project." + ] + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "domainId" + } + ], + "operationId": "delete-projects-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Delete a project domain", + "description": "Delete a single user-specified domain associated with a project.\n", + "x-property-id-kebab": "delete-projects-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Delete a single user-specified domain associated with a project." + ] + } + }, + "/projects/{projectId}/environment-types": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-environment-types", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentTypeCollection" + } + } + } + } + }, + "tags": [ + "Environment Type" + ], + "summary": "Get environment types", + "description": "List all available environment types", + "x-property-id-kebab": "list-projects-environment-types", + "x-tag-id-kebab": "Environment-Type", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\EnvironmentType[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\EnvironmentType[]" + }, + "x-returnable": true, + "x-description": [ + "List all available environment types" + ] + } + }, + "/projects/{projectId}/environment-types/{environmentTypeId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentTypeId" + } + ], + "operationId": "get-environment-type", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentType" + } + } + } + } + }, + "tags": [ + "Environment Type" + ], + "summary": "Get environment type links", + "description": "Lists the endpoints used to retrieve info about the environment type.", + "x-property-id-kebab": "get-environment-type", + "x-tag-id-kebab": "Environment-Type", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\EnvironmentType" + ], + "x-return-types-union": "\\Upsun\\Model\\EnvironmentType", + "x-phpdoc": { + "return": "\\Upsun\\Model\\EnvironmentType" + }, + "x-returnable": true, + "x-description": [ + "Lists the endpoints used to retrieve info about the environment type." + ] + } + }, + "/projects/{projectId}/environments": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-environments", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentCollection" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Get list of project environments", + "description": "Retrieve a list of a project's existing environments and the\ninformation associated with each environment.\n", + "x-property-id-kebab": "list-projects-environments", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Environment[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Environment[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a list of a project's existing environments and the information associated with each environment." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "get-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Environment" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Get an environment", + "description": "Retrieve the details of a single existing environment.", + "x-property-id-kebab": "get-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Environment" + ], + "x-return-types-union": "\\Upsun\\Model\\Environment", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Environment" + }, + "x-returnable": true, + "x-description": [ + "Retrieve the details of a single existing environment." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentPatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "update-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Update an environment", + "description": "Update the details of a single existing environment.", + "x-property-id-kebab": "update-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update the details of a single existing environment." + ] + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "delete-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Delete an environment", + "description": "Delete a specified environment.", + "x-property-id-kebab": "delete-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Delete a specified environment." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/activate": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "activate-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentActivateInput" + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Activate an environment", + "description": "Set the specified environment's status to active", + "x-property-id-kebab": "activate-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Set the specified environment's status to active" + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/activities": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "list-projects-environments-activities", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActivityCollection" + } + } + } + } + }, + "tags": [ + "Environment Activity" + ], + "summary": "Get environment activity log", + "description": "Retrieve an environment's activity log. This returns a list of object\nwith records of actions such as:\n\n- Commits being pushed to the repository\n- A new environment being branched out from the specified environment\n- A snapshot being created of the specified environment\n\nThe object includes a timestamp of when the action occurred\n(`created_at`), when the action concluded (`updated_at`),\nthe current `state` of the action, the action's completion\npercentage (`completion_percent`), and other related information in\nthe `payload`.\n\nThe contents of the `payload` varies based on the `type` of the\nactivity. For example:\n\n- An `environment.branch` action's `payload` can contain objects\nrepresenting the `parent` environment and the branching action's\n`outcome`.\n\n- An `environment.push` action's `payload` can contain objects\nrepresenting the `environment`, the specific `commits` included in\nthe push, and the `user` who pushed.\n", + "x-property-id-kebab": "list-projects-environments-activities", + "x-tag-id-kebab": "Environment-Activity", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Activity[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Activity[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve an environment's activity log. This returns a list of object with records of actions such as: - Commits", + "being pushed to the repository - A new environment being branched out from the specified environment - A snapshot", + "being created of the specified environment The object includes a timestamp of when the action occurred", + "(`created_at`), when the action concluded (`updated_at`), the current `state` of the action, the action's", + "completion percentage (`completion_percent`), and other related information in the `payload`. The contents of the", + "`payload` varies based on the `type` of the activity. For example: - An `environment.branch` action's `payload`", + "can contain objects representing the `parent` environment and the branching action's `outcome`. - An", + "`environment.push` action's `payload` can contain objects representing the `environment`, the specific `commits`", + "included in the push, and the `user` who pushed." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/activities/{activityId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "activityId" + } + ], + "operationId": "get-projects-environments-activities", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Activity" + } + } + } + } + }, + "tags": [ + "Environment Activity" + ], + "summary": "Get an environment activity log entry", + "description": "Retrieve a single environment activity entry as specified by an\n`id` returned by the\n[Get environment activities list](#tag/Environment-Activity%2Fpaths%2F~1projects~1%7BprojectId%7D~1environments~1%7BenvironmentId%7D~1activities%2Fget)\nendpoint. See the documentation on that endpoint for details about\nthe information this endpoint can return.\n", + "x-property-id-kebab": "get-projects-environments-activities", + "x-tag-id-kebab": "Environment-Activity", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Activity" + ], + "x-return-types-union": "\\Upsun\\Model\\Activity", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Activity" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a single environment activity entry as specified by an `id` returned by the Get environment activities", + "list", + "(https://docs.upsun.com/api/#tag/Environment-Activity/paths//projects/{projectId}/environments/{environmentId}/activities/get)", + "endpoint. See the documentation on that endpoint for details about the information this endpoint can return." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/activities/{activityId}/cancel": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "activityId" + } + ], + "operationId": "action-projects-environments-activities-cancel", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment Activity" + ], + "summary": "Cancel an environment activity", + "description": "Cancel a single activity as specified by an `id` returned by the\n[Get environment activities list](#tag/Environment-Activity%2Fpaths%2F~1projects~1%7BprojectId%7D~1environments~1%7BenvironmentId%7D~1activities%2Fget)\nendpoint.\n\nPlease note that not all activities are cancelable.\n", + "x-property-id-kebab": "action-projects-environments-activities-cancel", + "x-tag-id-kebab": "Environment-Activity", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Cancel a single activity as specified by an `id` returned by the Get environment activities list", + "(https://docs.upsun.com/api/#tag/Environment-Activity/paths//projects/{projectId}/environments/{environmentId}/activities/get)", + "endpoint. Please note that not all activities are cancelable." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/backup": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "backup-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentBackupInput" + } + } + } + }, + "tags": [ + "Environment Backups" + ], + "summary": "Create backup of environment", + "description": "Trigger a new backup of an environment to be created. See the\n[Backups](https://docs.upsun.com/anchors/environments/backup/)\nsection of the documentation for more information.\n", + "x-property-id-kebab": "backup-environment", + "x-tag-id-kebab": "Environment-Backups", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Trigger a new backup of an environment to be created. See the", + "[Backups](https://docs.upsun.com/anchors/environments/backup/) section of the documentation for more information." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/backups": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "list-projects-environments-backups", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackupCollection" + } + } + } + } + }, + "tags": [ + "Environment Backups" + ], + "summary": "Get an environment's backup list", + "description": "Retrieve a list of objects representing backups of this environment.\n", + "x-stability": "EXPERIMENTAL", + "x-property-id-kebab": "list-projects-environments-backups", + "x-tag-id-kebab": "Environment-Backups", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Backup[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Backup[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a list of objects representing backups of this environment." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/backups/{backupId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "backupId" + } + ], + "operationId": "get-projects-environments-backups", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Backup" + } + } + } + } + }, + "tags": [ + "Environment Backups" + ], + "summary": "Get an environment backup's info", + "description": "Get the details of a specific backup from an environment using the `id`\nof the entry retrieved by the\n[Get backups list](#tag/Environment-Backups%2Fpaths%2F~1projects~1%7BprojectId%7D~1environments~1%7BenvironmentId%7D~1backups%2Fget)\nendpoint.\n", + "x-stability": "EXPERIMENTAL", + "x-property-id-kebab": "get-projects-environments-backups", + "x-tag-id-kebab": "Environment-Backups", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Backup" + ], + "x-return-types-union": "\\Upsun\\Model\\Backup", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Backup" + }, + "x-returnable": true, + "x-description": [ + "Get the details of a specific backup from an environment using the `id` of the entry retrieved by the Get backups", + "list", + "(https://docs.upsun.com/api/#tag/Environment-Backups/paths//projects/{projectId}/environments/{environmentId}/backups/get)", + "endpoint." + ] + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "backupId" + } + ], + "operationId": "delete-projects-environments-backups", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment Backups" + ], + "summary": "Delete an environment backup", + "description": "Delete a specific backup from an environment using the `id`\nof the entry retrieved by the\n[Get backups list](#tag/Environment-Backups%2Fpaths%2F~1projects~1%7BprojectId%7D~1environments~1%7BenvironmentId%7D~1backups%2Fget)\nendpoint.\n", + "x-stability": "EXPERIMENTAL", + "x-property-id-kebab": "delete-projects-environments-backups", + "x-tag-id-kebab": "Environment-Backups", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Delete a specific backup from an environment using the `id` of the entry retrieved by the Get backups list", + "(https://docs.upsun.com/api/#tag/Environment-Backups/paths//projects/{projectId}/environments/{environmentId}/backups/get)", + "endpoint." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/backups/{backupId}/restore": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "backupId" + } + ], + "operationId": "restore-backup", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentRestoreInput" + } + } + } + }, + "tags": [ + "Environment Backups" + ], + "summary": "Restore an environment snapshot", + "description": "Restore a specific backup from an environment using the `id`\nof the entry retrieved by the\n[Get backups list](#tag/Environment-Backups%2Fpaths%2F~1projects~1%7BprojectId%7D~1environments~1%7BenvironmentId%7D~1backups%2Fget)\nendpoint.\n", + "x-stability": "EXPERIMENTAL", + "x-property-id-kebab": "restore-backup", + "x-tag-id-kebab": "Environment-Backups", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Restore a specific backup from an environment using the `id` of the entry retrieved by the Get backups list", + "(https://docs.upsun.com/api/#tag/Environment-Backups/paths//projects/{projectId}/environments/{environmentId}/backups/get)", + "endpoint." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/branch": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "branch-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentBranchInput" + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Branch an environment", + "description": "Create a new environment as a branch of the current environment.\n", + "x-property-id-kebab": "branch-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Create a new environment as a branch of the current environment." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/deactivate": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "deactivate-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Deactivate an environment", + "description": "Destroy all services and data running on this environment so that\nonly the Git branch remains. The environment can be reactivated\nlater at any time; reactivating an environment will sync data\nfrom the parent environment and redeploy.\n\n**NOTE: ALL DATA IN THIS ENVIRONMENT WILL BE IRREVOCABLY LOST**\n", + "x-property-id-kebab": "deactivate-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Destroy all services and data running on this environment so that only the Git branch remains. The environment", + "can be reactivated later at any time; reactivating an environment will sync data from the parent environment and", + "redeploy. **NOTE: ALL DATA IN THIS ENVIRONMENT WILL BE IRREVOCABLY LOST**" + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/deploy": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "deploy-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentDeployInput" + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Deploy an environment", + "description": "Trigger a controlled [manual deployment](https://docs.upsun.com/learn/overview/build-deploy.html#manual-deployment)\nto release all the staged changes\n", + "x-property-id-kebab": "deploy-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Trigger a controlled [manual", + "deployment](https://docs.upsun.com/learn/overview/build-deploy.html#manual-deployment) to release all the staged", + "changes" + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/deployments": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "list-projects-environments-deployments", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeploymentCollection" + } + } + } + } + }, + "tags": [ + "Deployment" + ], + "summary": "Get an environment's deployment information", + "description": "Retrieve the read-only configuration of an environment's deployment.\nThe returned information is everything required to\nrecreate a project's current deployment.\n\nMore specifically, the objects\nreturned by this endpoint contain the configuration derived from the\nrepository's YAML configuration file: `.upsun/config.yaml`.\n\nAdditionally, any values deriving from environment variables, the\ndomains attached to a project, project access settings, etc. are\nincluded here.\n\nThis endpoint currently returns a list containing a single deployment\nconfiguration with an `id` of `current`. This may be subject to change\nin the future.\n", + "x-property-id-kebab": "list-projects-environments-deployments", + "x-tag-id-kebab": "Deployment", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Deployment[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Deployment[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve the read-only configuration of an environment's deployment. The returned information is everything", + "required to recreate a project's current deployment. More specifically, the objects returned by this endpoint", + "contain the configuration derived from the repository's YAML configuration file: `.upsun/config.yaml`.", + "Additionally, any values deriving from environment variables, the domains attached to a project, project access", + "settings, etc. are included here. This endpoint currently returns a list containing a single deployment", + "configuration with an `id` of `current`. This may be subject to change in the future." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/deployments/{deploymentId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "deploymentId" + } + ], + "operationId": "get-projects-environments-deployments", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Deployment" + } + } + } + } + }, + "tags": [ + "Deployment" + ], + "summary": "Get a single environment deployment", + "description": "Retrieve a single deployment configuration with an id of `current`. This may be subject to change in the future.\nOnly `current` can be queried.\n", + "x-property-id-kebab": "get-projects-environments-deployments", + "x-tag-id-kebab": "Deployment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Deployment" + ], + "x-return-types-union": "\\Upsun\\Model\\Deployment", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Deployment" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a single deployment configuration with an id of `current`. This may be subject to change in the future.", + "Only `current` can be queried." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/deployments/{deploymentId}/operations": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "deploymentId" + } + ], + "operationId": "run-operation", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentOperationInput" + } + } + } + }, + "tags": [ + "Runtime Operations" + ], + "summary": "Execute a runtime operation", + "description": "Execute a runtime operation on a currently deployed environment. This allows you to run one-off commands, such as rebuilding static assets on demand, by defining an `operations` key in a project's `.upsun/config.yaml` configuration. More information on runtime operations is [available in our user documentation](https://docs.upsun.com/anchors/app/runtime-operations/).", + "x-property-id-kebab": "run-operation", + "x-tag-id-kebab": "Runtime-Operations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Execute a runtime operation on a currently deployed environment. This allows you to run one-off commands, such as", + "rebuilding static assets on demand, by defining an `operations` key in a project's `.upsun/config.yaml`", + "configuration. More information on runtime operations is [available in our user", + "documentation](https://docs.upsun.com/anchors/app/runtime-operations/)." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/domains": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "list-projects-environments-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DomainCollection" + } + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Get a list of environment domains", + "description": "Retrieve a list of objects representing the user-specified domains\nassociated with an environment. Note that this does *not* return the\n`.platformsh.site` subdomains, which are automatically assigned to\nthe environment.\n", + "x-property-id-kebab": "list-projects-environments-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Domain[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Domain[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a list of objects representing the user-specified domains associated with an environment. Note that this", + "does *not* return the `.platformsh.site` subdomains, which are automatically assigned to the environment." + ] + }, + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "create-projects-environments-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DomainCreateInput" + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Add an environment domain", + "description": "Add a single domain to an environment.\nIf the environment is not production, the `replacement_for` field\nis required, which binds a new domain to an existing one from a\nproduction environment.\nIf the `ssl` field is left blank without an object containing\na PEM-encoded SSL certificate, a certificate will\n[be provisioned for you via Let's Encrypt](https://docs.upsun.com/anchors/routes/https/certificates/).\n", + "x-property-id-kebab": "create-projects-environments-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Add a single domain to an environment. If the environment is not production, the `replacement_for` field is", + "required, which binds a new domain to an existing one from a production environment. If the `ssl` field is left", + "blank without an object containing a PEM-encoded SSL certificate, a certificate will [be provisioned for you via", + "Let's Encrypt](https://docs.upsun.com/anchors/routes/https/certificates/)." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/domains/{domainId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "domainId" + } + ], + "operationId": "get-projects-environments-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Domain" + } + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Get an environment domain", + "description": "Retrieve information about a single user-specified domain\nassociated with an environment.\n", + "x-property-id-kebab": "get-projects-environments-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Domain" + ], + "x-return-types-union": "\\Upsun\\Model\\Domain", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Domain" + }, + "x-returnable": true, + "x-description": [ + "Retrieve information about a single user-specified domain associated with an environment." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DomainPatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "domainId" + } + ], + "operationId": "update-projects-environments-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Update an environment domain", + "description": "Update the information associated with a single user-specified\ndomain associated with an environment.\n", + "x-property-id-kebab": "update-projects-environments-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update the information associated with a single user-specified domain associated with an environment." + ] + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "domainId" + } + ], + "operationId": "delete-projects-environments-domains", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Domain Management" + ], + "summary": "Delete an environment domain", + "description": "Delete a single user-specified domain associated with an environment.\n", + "x-property-id-kebab": "delete-projects-environments-domains", + "x-tag-id-kebab": "Domain-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Delete a single user-specified domain associated with an environment." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/initialize": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "initialize-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentInitializeInput" + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Initialize a new environment", + "description": "Initialize and configure a new environment with an existing repository.\nThe payload is the url of a git repository with a profile name:\n\n```\n{\n \"repository\": \"git@github.com:platformsh/a-project-template.git@master\",\n \"profile\": \"Example Project\",\n \"files\": [\n {\n \"mode\": 0600,\n \"path\": \"config.json\",\n \"contents\": \"XXXXXXXX\"\n }\n ]\n}\n```\nIt can optionally carry additional files that will be committed to the\nrepository, the POSIX file mode to set on each file, and the base64-encoded\ncontents of each file.\n\nThis endpoint can also add a second repository\nURL in the `config` parameter that will be added to the contents of the first.\nThis allows you to put your application in one repository and the Upsun\nYAML configuration files in another.\n", + "x-property-id-kebab": "initialize-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Initialize and configure a new environment with an existing repository. The payload is the url of a git", + "repository with a profile name: ``` { \"repository\": \"git@github.com:platformsh/a-project-template.git@master\",", + "\"profile\": \"Example Project\", \"files\": [ { \"mode\": 0600, \"path\": \"config.json\", \"contents\": \"XXXXXXXX\" } ] } ```", + "It can optionally carry additional files that will be committed to the repository, the POSIX file mode to set on", + "each file, and the base64-encoded contents of each file. This endpoint can also add a second repository URL in", + "the `config` parameter that will be added to the contents of the first. This allows you to put your application", + "in one repository and the Upsun YAML configuration files in another." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/merge": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "merge-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentMergeInput" + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Merge an environment", + "description": "Merge an environment into its parent. This means that code changes\nfrom the branch environment will be merged into the parent branch, and\nthe parent branch will be rebuilt and deployed with the new code changes,\nretaining the existing data in the parent environment.\n", + "x-property-id-kebab": "merge-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Merge an environment into its parent. This means that code changes from the branch environment will be merged", + "into the parent branch, and the parent branch will be rebuilt and deployed with the new code changes, retaining", + "the existing data in the parent environment." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/pause": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "pause-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Pause an environment", + "description": "Pause an environment, stopping all services and applications (except the router).\n\nDevelopment environments are often used for a limited time and then abandoned.\nTo prevent unnecessary consumption of resources, development environments that\nhaven't been redeployed in 14 days are automatically paused.\n\nYou can pause an environment manually at any time using this endpoint. Further\ninformation is available in our [public documentation](https://docs.upsun.com/anchors/environments/paused/).\n", + "x-property-id-kebab": "pause-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Pause an environment, stopping all services and applications (except the router). Development environments are", + "often used for a limited time and then abandoned. To prevent unnecessary consumption of resources, development", + "environments that haven't been redeployed in 14 days are automatically paused. You can pause an environment", + "manually at any time using this endpoint. Further information is available in our [public", + "documentation](https://docs.upsun.com/anchors/environments/paused/)." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/redeploy": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "redeploy-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Redeploy an environment", + "description": "Trigger the redeployment sequence of an environment.", + "x-property-id-kebab": "redeploy-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Trigger the redeployment sequence of an environment." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/resume": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "resume-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Resume a paused environment", + "description": "Resume a paused environment, restarting all services and applications.\n\nDevelopment environments that haven't been used for 14 days will be paused\nautomatically. They can be resumed via a redeployment or manually using this\nendpoint or the CLI as described in the [public documentation](https://docs.upsun.com/anchors/environments/paused/).\n", + "x-property-id-kebab": "resume-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Resume a paused environment, restarting all services and applications. Development environments that haven't been", + "used for 14 days will be paused automatically. They can be resumed via a redeployment or manually using this", + "endpoint or the CLI as described in the [public", + "documentation](https://docs.upsun.com/anchors/environments/paused/)." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/routes": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "list-projects-environments-routes", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RouteCollection" + } + } + } + } + }, + "tags": [ + "Routing" + ], + "summary": "Get list of routes", + "description": "Retrieve a list of objects containing route definitions for\na specific environment. The definitions returned by this endpoint\nare those present in an environment's `.upsun/config.yaml` file.\n", + "x-property-id-kebab": "list-projects-environments-routes", + "x-tag-id-kebab": "Routing", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Route[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Route[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a list of objects containing route definitions for a specific environment. The definitions returned by", + "this endpoint are those present in an environment's `.upsun/config.yaml` file." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/routes/{routeId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "routeId" + } + ], + "operationId": "get-projects-environments-routes", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Route" + } + } + } + } + }, + "tags": [ + "Routing" + ], + "summary": "Get a route's info", + "description": "Get details of a route from an environment using the `id` of the entry\nretrieved by the [Get environment routes list](#tag/Environment-Routes%2Fpaths%2F~1projects~1%7BprojectId%7D~1environments~1%7BenvironmentId%7D~1routes%2Fget)\nendpoint.\n", + "x-property-id-kebab": "get-projects-environments-routes", + "x-tag-id-kebab": "Routing", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Route" + ], + "x-return-types-union": "\\Upsun\\Model\\Route", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Route" + }, + "x-returnable": true, + "x-description": [ + "Get details of a route from an environment using the `id` of the entry retrieved by the Get environment routes", + "list", + "(https://docs.upsun.com/api/#tag/Environment-Routes/paths//projects/{projectId}/environments/{environmentId}/routes/get)", + "endpoint." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/source-operation": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "run-source-operation", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentSourceOperationInput" + } + } + } + }, + "tags": [ + "Source Operations" + ], + "summary": "Trigger a source operation", + "description": "This endpoint triggers a source code operation as defined in the `source.operations`\nkey in a project's `.upsun/config.yaml` configuration. More information\non source code operations is\n[available in our user documentation](https://docs.upsun.com/anchors/app/reference/source/operations/).\n", + "x-property-id-kebab": "run-source-operation", + "x-tag-id-kebab": "Source-Operations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "This endpoint triggers a source code operation as defined in the `source.operations` key in a project's", + "`.upsun/config.yaml` configuration. More information on source code operations is [available in our user", + "documentation](https://docs.upsun.com/anchors/app/reference/source/operations/)." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/source-operations": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "list-projects-environments-source-operations", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentSourceOperationCollection" + } + } + } + } + }, + "tags": [ + "Source Operations" + ], + "summary": "List source operations", + "description": "Lists all the source operations, defined in `.upsun/config.yaml`, that are available in an environment.\nMore information on source code operations is\n[available in our user documentation](https://docs.upsun.com/anchors/app/reference/source/operations/).\n", + "x-property-id-kebab": "list-projects-environments-source-operations", + "x-tag-id-kebab": "Source-Operations", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\EnvironmentSourceOperation[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\EnvironmentSourceOperation[]" + }, + "x-returnable": true, + "x-description": [ + "Lists all the source operations, defined in `.upsun/config.yaml`, that are available in an environment. More", + "information on source code operations is [available in our user", + "documentation](https://docs.upsun.com/anchors/app/reference/source/operations/)." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/synchronize": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "synchronize-environment", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentSynchronizeInput" + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Synchronize a child environment with its parent", + "description": "This synchronizes the code and/or data of an environment with that of\nits parent, then redeploys the environment. Synchronization is only\npossible if a branch has no unmerged commits and it can be fast-forwarded.\n\nIf data synchronization is specified, the data in the environment will\nbe overwritten with that of its parent.\n", + "x-property-id-kebab": "synchronize-environment", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "This synchronizes the code and/or data of an environment with that of its parent, then redeploys the environment.", + "Synchronization is only possible if a branch has no unmerged commits and it can be fast-forwarded. If data", + "synchronization is specified, the data in the environment will be overwritten with that of its parent." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/variables": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "list-projects-environments-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentVariableCollection" + } + } + } + } + }, + "tags": [ + "Environment Variables" + ], + "summary": "Get list of environment variables", + "description": "Retrieve a list of objects representing the user-defined variables\nwithin an environment.\n", + "x-property-id-kebab": "list-projects-environments-variables", + "x-tag-id-kebab": "Environment-Variables", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\EnvironmentVariable[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\EnvironmentVariable[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a list of objects representing the user-defined variables within an environment." + ] + }, + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "create-projects-environments-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentVariableCreateInput" + } + } + } + }, + "tags": [ + "Environment Variables" + ], + "summary": "Add an environment variable", + "description": "Add a variable to an environment. The `value` can be either a string or a JSON\nobject (default: string), as specified by the `is_json` boolean flag.\nAdditionally, the inheritability of an environment variable can be\ndetermined through the `is_inheritable` flag (default: true).\nSee the [Environment Variables](https://docs.upsun.com/anchors/variables/set/environment/create/)\nsection in our documentation for more information.\n", + "x-property-id-kebab": "create-projects-environments-variables", + "x-tag-id-kebab": "Environment-Variables", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Add a variable to an environment. The `value` can be either a string or a JSON object (default: string), as", + "specified by the `is_json` boolean flag. Additionally, the inheritability of an environment variable can be", + "determined through the `is_inheritable` flag (default: true). See the [Environment", + "Variables](https://docs.upsun.com/anchors/variables/set/environment/create/) section in our documentation for", + "more information." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/variables/{variableId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "variableId" + } + ], + "operationId": "get-projects-environments-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentVariable" + } + } + } + } + }, + "tags": [ + "Environment Variables" + ], + "summary": "Get an environment variable", + "description": "Retrieve a single user-defined environment variable.", + "x-property-id-kebab": "get-projects-environments-variables", + "x-tag-id-kebab": "Environment-Variables", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\EnvironmentVariable" + ], + "x-return-types-union": "\\Upsun\\Model\\EnvironmentVariable", + "x-phpdoc": { + "return": "\\Upsun\\Model\\EnvironmentVariable" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a single user-defined environment variable." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnvironmentVariablePatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "variableId" + } + ], + "operationId": "update-projects-environments-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment Variables" + ], + "summary": "Update an environment variable", + "description": "Update a single user-defined environment variable.\nThe `value` can be either a string or a JSON\nobject (default: string), as specified by the `is_json` boolean flag.\nAdditionally, the inheritability of an environment variable can be\ndetermined through the `is_inheritable` flag (default: true).\nSee the [Variables](https://docs.upsun.com/anchors/variables/)\nsection in our documentation for more information.\n", + "x-property-id-kebab": "update-projects-environments-variables", + "x-tag-id-kebab": "Environment-Variables", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update a single user-defined environment variable. The `value` can be either a string or a JSON object (default:", + "string), as specified by the `is_json` boolean flag. Additionally, the inheritability of an environment variable", + "can be determined through the `is_inheritable` flag (default: true). See the", + "[Variables](https://docs.upsun.com/anchors/variables/) section in our documentation for more information." + ] + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "variableId" + } + ], + "operationId": "delete-projects-environments-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment Variables" + ], + "summary": "Delete an environment variable", + "description": "Delete a single user-defined environment variable.", + "x-property-id-kebab": "delete-projects-environments-variables", + "x-tag-id-kebab": "Environment-Variables", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Delete a single user-defined environment variable." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/versions": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "list-projects-environments-versions", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionCollection" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "List versions associated with the environment", + "description": "List versions associated with the `{environmentId}` environment.\nAt least one version always exists.\nWhen multiple versions exist, it means that multiple versions of an app are deployed.\nThe deployment target type denotes whether staged deployment is supported.\n", + "x-property-id-kebab": "list-projects-environments-versions", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Version[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Version[]" + }, + "x-returnable": true, + "x-description": [ + "List versions associated with the `{environmentId}` environment. At least one version always exists. When", + "multiple versions exist, it means that multiple versions of an app are deployed. The deployment target type", + "denotes whether staged deployment is supported." + ] + }, + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + } + ], + "operationId": "create-projects-environments-versions", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionCreateInput" + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Create versions associated with the environment", + "description": "Create versions associated with the `{environmentId}` environment.\nAt least one version always exists.\nWhen multiple versions exist, it means that multiple versions of an app are deployed.\nThe deployment target type denotes whether staged deployment is supported.\n", + "x-property-id-kebab": "create-projects-environments-versions", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Create versions associated with the `{environmentId}` environment. At least one version always exists. When", + "multiple versions exist, it means that multiple versions of an app are deployed. The deployment target type", + "denotes whether staged deployment is supported." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/versions/{versionId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "versionId" + } + ], + "operationId": "get-projects-environments-versions", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Version" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "List the version", + "description": "List the `{versionId}` version.\nA routing percentage for this version may be specified for staged rollouts\n(if the deployment target supports it).\n", + "x-property-id-kebab": "get-projects-environments-versions", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Version" + ], + "x-return-types-union": "\\Upsun\\Model\\Version", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Version" + }, + "x-returnable": true, + "x-description": [ + "List the `{versionId}` version. A routing percentage for this version may be specified for staged rollouts (if", + "the deployment target supports it)." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionPatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "versionId" + } + ], + "operationId": "update-projects-environments-versions", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Update the version", + "description": "Update the `{versionId}` version.\nA routing percentage for this version may be specified for staged rollouts\n(if the deployment target supports it).\n", + "x-property-id-kebab": "update-projects-environments-versions", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update the `{versionId}` version. A routing percentage for this version may be specified for staged rollouts (if", + "the deployment target supports it)." + ] + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "environmentId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "versionId" + } + ], + "operationId": "delete-projects-environments-versions", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Environment" + ], + "summary": "Delete the version", + "description": "Delete the `{versionId}` version.\nA routing percentage for this version may be specified for staged rollouts\n(if the deployment target supports it).\n", + "x-property-id-kebab": "delete-projects-environments-versions", + "x-tag-id-kebab": "Environment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Delete the `{versionId}` version. A routing percentage for this version may be specified for staged rollouts (if", + "the deployment target supports it)." + ] + } + }, + "/projects/{projectId}/git/blobs/{repositoryBlobId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "repositoryBlobId" + } + ], + "operationId": "get-projects-git-blobs", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Blob" + } + } + } + } + }, + "tags": [ + "Repository" + ], + "summary": "Get a blob object", + "description": "Retrieve, by hash, an object representing a blob in the repository\nbacking a project. This endpoint allows direct read-only access\nto the contents of files in a repo. It returns the file in the\n`content` field of the response object, encoded according to the\nformat in the `encoding` field, e.g. `base64`.\n", + "x-property-id-kebab": "get-projects-git-blobs", + "x-tag-id-kebab": "Repository", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Blob" + ], + "x-return-types-union": "\\Upsun\\Model\\Blob", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Blob" + }, + "x-returnable": true, + "x-description": [ + "Retrieve, by hash, an object representing a blob in the repository backing a project. This endpoint allows direct", + "read-only access to the contents of files in a repo. It returns the file in the `content` field of the response", + "object, encoded according to the format in the `encoding` field, e.g. `base64`." + ] + } + }, + "/projects/{projectId}/git/commits/{repositoryCommitId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "repositoryCommitId" + } + ], + "operationId": "get-projects-git-commits", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Commit" + } + } + } + } + }, + "tags": [ + "Repository" + ], + "summary": "Get a commit object", + "description": "Retrieve, by hash, an object representing a commit in the repository backing\na project. This endpoint functions similarly to `git cat-file -p `.\nThe returned object contains the hash of the Git tree that it\nbelongs to, as well as the ID of parent commits.\n\nThe commit represented by a parent ID can be retrieved using this\nendpoint, while the tree state represented by this commit can\nbe retrieved using the\n[Get a tree object](#tag/Git-Repo%2Fpaths%2F~1projects~1%7BprojectId%7D~1git~1trees~1%7BrepositoryTreeId%7D%2Fget)\nendpoint.\n", + "x-property-id-kebab": "get-projects-git-commits", + "x-tag-id-kebab": "Repository", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Commit" + ], + "x-return-types-union": "\\Upsun\\Model\\Commit", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Commit" + }, + "x-returnable": true, + "x-description": [ + "Retrieve, by hash, an object representing a commit in the repository backing a project. This endpoint functions", + "similarly to `git cat-file -p `. The returned object contains the hash of the Git tree that it belongs", + "to, as well as the ID of parent commits. The commit represented by a parent ID can be retrieved using this", + "endpoint, while the tree state represented by this commit can be retrieved using the Get a tree object", + "(https://docs.upsun.com/api/#tag/Git-Repo/paths//projects/{projectId}/git/trees/{repositoryTreeId}/get) endpoint." + ] + } + }, + "/projects/{projectId}/git/refs": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-git-refs", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefCollection" + } + } + } + } + }, + "tags": [ + "Repository" + ], + "summary": "Get list of repository refs", + "description": "Retrieve a list of `refs/*` in the repository backing a project.\nThis endpoint functions similarly to `git show-ref`, with each\nreturned object containing a `ref` field with the ref's name,\nand an object containing the associated commit ID.\n\nThe returned commit ID can be used with the\n[Get a commit object](#tag/Git-Repo%2Fpaths%2F~1projects~1%7BprojectId%7D~1git~1commits~1%7BrepositoryCommitId%7D%2Fget)\nendpoint to retrieve information about that specific commit.\n", + "x-property-id-kebab": "list-projects-git-refs", + "x-tag-id-kebab": "Repository", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Ref[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Ref[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a list of `refs/*` in the repository backing a project. This endpoint functions similarly to `git", + "show-ref`, with each returned object containing a `ref` field with the ref's name, and an object containing the", + "associated commit ID. The returned commit ID can be used with the Get a commit object", + "(https://docs.upsun.com/api/#tag/Git-Repo/paths//projects/{projectId}/git/commits/{repositoryCommitId}/get)", + "endpoint to retrieve information about that specific commit." + ] + } + }, + "/projects/{projectId}/git/refs/{repositoryRefId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "repositoryRefId" + } + ], + "operationId": "get-projects-git-refs", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ref" + } + } + } + } + }, + "tags": [ + "Repository" + ], + "summary": "Get a ref object", + "description": "Retrieve the details of a single `refs` object in the repository\nbacking a project. This endpoint functions similarly to\n`git show-ref `, although the pattern must be a full ref `id`,\nrather than a matching pattern.\n\n*NOTE: The `{repositoryRefId}` must be properly escaped.*\nThat is, the ref `refs/heads/master` is accessible via\n`/projects/{projectId}/git/refs/heads%2Fmaster`.\n", + "x-property-id-kebab": "get-projects-git-refs", + "x-tag-id-kebab": "Repository", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Ref" + ], + "x-return-types-union": "\\Upsun\\Model\\Ref", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Ref" + }, + "x-returnable": true, + "x-description": [ + "Retrieve the details of a single `refs` object in the repository backing a project. This endpoint functions", + "similarly to `git show-ref `, although the pattern must be a full ref `id`, rather than a matching", + "pattern. *NOTE: The `{repositoryRefId}` must be properly escaped.* That is, the ref `refs/heads/master` is", + "accessible via `/projects/{projectId}/git/refs/heads/master`." + ] + } + }, + "/projects/{projectId}/git/trees/{repositoryTreeId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "repositoryTreeId" + } + ], + "operationId": "get-projects-git-trees", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Tree" + } + } + } + } + }, + "tags": [ + "Repository" + ], + "summary": "Get a tree object", + "description": "Retrieve, by hash, the tree state represented by a commit.\nThe returned object's `tree` field contains a list of files and\ndirectories present in the tree.\n\nDirectories in the tree can be recursively retrieved by this endpoint\nthrough their hashes. Files in the tree can be retrieved by the\n[Get a blob object](#tag/Git-Repo%2Fpaths%2F~1projects~1%7BprojectId%7D~1git~1blobs~1%7BrepositoryBlobId%7D%2Fget)\nendpoint.\n", + "x-property-id-kebab": "get-projects-git-trees", + "x-tag-id-kebab": "Repository", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Tree" + ], + "x-return-types-union": "\\Upsun\\Model\\Tree", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Tree" + }, + "x-returnable": true, + "x-description": [ + "Retrieve, by hash, the tree state represented by a commit. The returned object's `tree` field contains a list of", + "files and directories present in the tree. Directories in the tree can be recursively retrieved by this endpoint", + "through their hashes. Files in the tree can be retrieved by the Get a blob object", + "(https://docs.upsun.com/api/#tag/Git-Repo/paths//projects/{projectId}/git/blobs/{repositoryBlobId}/get) endpoint." + ] + } + }, + "/projects/{projectId}/integrations": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-integrations", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationCollection" + } + } + } + } + }, + "tags": [ + "Third-Party Integrations" + ], + "summary": "Get list of existing integrations for a project", + "x-property-id-kebab": "list-projects-integrations", + "x-tag-id-kebab": "Third-Party-Integrations", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\Integration[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Integration[]" + }, + "x-returnable": true + }, + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "create-projects-integrations", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationCreateInput" + } + } + } + }, + "tags": [ + "Third-Party Integrations" + ], + "summary": "Integrate project with a third-party service", + "x-property-id-kebab": "create-projects-integrations", + "x-tag-id-kebab": "Third-Party-Integrations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true + } + }, + "/projects/{projectId}/integrations/{integrationId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "integrationId" + } + ], + "operationId": "get-projects-integrations", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Integration" + } + } + } + } + }, + "tags": [ + "Third-Party Integrations" + ], + "summary": "Get information about an existing third-party integration", + "x-property-id-kebab": "get-projects-integrations", + "x-tag-id-kebab": "Third-Party-Integrations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Integration" + ], + "x-return-types-union": "\\Upsun\\Model\\Integration", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Integration" + }, + "x-returnable": true + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationPatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "integrationId" + } + ], + "operationId": "update-projects-integrations", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Third-Party Integrations" + ], + "summary": "Update an existing third-party integration", + "x-property-id-kebab": "update-projects-integrations", + "x-tag-id-kebab": "Third-Party-Integrations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "integrationId" + } + ], + "operationId": "delete-projects-integrations", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Third-Party Integrations" + ], + "summary": "Delete an existing third-party integration", + "x-property-id-kebab": "delete-projects-integrations", + "x-tag-id-kebab": "Third-Party-Integrations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true + } + }, + "/projects/{projectId}/provisioners": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-provisioners", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CertificateProvisionerCollection" + } + } + } + } + }, + "tags": [ + "Cert Management" + ], + "x-property-id-kebab": "list-projects-provisioners", + "x-tag-id-kebab": "Cert-Management", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\CertificateProvisioner[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\CertificateProvisioner[]" + }, + "x-returnable": true + } + }, + "/projects/{projectId}/provisioners/{certificateProvisionerDocumentId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "certificateProvisionerDocumentId" + } + ], + "operationId": "get-projects-provisioners", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CertificateProvisioner" + } + } + } + } + }, + "tags": [ + "Cert Management" + ], + "x-property-id-kebab": "get-projects-provisioners", + "x-tag-id-kebab": "Cert-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\CertificateProvisioner" + ], + "x-return-types-union": "\\Upsun\\Model\\CertificateProvisioner", + "x-phpdoc": { + "return": "\\Upsun\\Model\\CertificateProvisioner" + }, + "x-returnable": true + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CertificateProvisionerPatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "certificateProvisionerDocumentId" + } + ], + "operationId": "update-projects-provisioners", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Cert Management" + ], + "x-property-id-kebab": "update-projects-provisioners", + "x-tag-id-kebab": "Cert-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true + } + }, + "/projects/{projectId}/settings": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "get-projects-settings", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectSettings" + } + } + } + } + }, + "tags": [ + "Project Settings" + ], + "summary": "Get list of project settings", + "description": "Retrieve the global settings for a project.", + "x-property-id-kebab": "get-projects-settings", + "x-tag-id-kebab": "Project-Settings", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\ProjectSettings" + ], + "x-return-types-union": "\\Upsun\\Model\\ProjectSettings", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ProjectSettings" + }, + "x-returnable": true, + "x-description": [ + "Retrieve the global settings for a project." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectSettingsPatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "update-projects-settings", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Project Settings" + ], + "summary": "Update a project setting", + "description": "Update one or more project-level settings.", + "x-property-id-kebab": "update-projects-settings", + "x-tag-id-kebab": "Project-Settings", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update one or more project-level settings." + ] + } + }, + "/projects/{projectId}/system": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "get-projects-system", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SystemInformation" + } + } + } + } + }, + "tags": [ + "System Information" + ], + "summary": "Get information about the Git server.", + "description": "Output information for the project.", + "x-property-id-kebab": "get-projects-system", + "x-tag-id-kebab": "System-Information", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\SystemInformation" + ], + "x-return-types-union": "\\Upsun\\Model\\SystemInformation", + "x-phpdoc": { + "return": "\\Upsun\\Model\\SystemInformation" + }, + "x-returnable": true, + "x-description": [ + "Output information for the project." + ] + } + }, + "/projects/{projectId}/system/restart": { + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "action-projects-system-restart", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "System Information" + ], + "summary": "Restart the Git server", + "description": "Force the Git server to restart.", + "x-property-id-kebab": "action-projects-system-restart", + "x-tag-id-kebab": "System-Information", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Force the Git server to restart." + ] + } + }, + "/projects/{projectId}/variables": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "list-projects-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectVariableCollection" + } + } + } + } + }, + "tags": [ + "Project Variables" + ], + "summary": "Get list of project variables", + "description": "Retrieve a list of objects representing the user-defined variables\nwithin a project.\n", + "x-property-id-kebab": "list-projects-variables", + "x-tag-id-kebab": "Project-Variables", + "x-return-types-displayReturn": true, + "x-return-types": [ + "\\Upsun\\Model\\ProjectVariable[]" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ProjectVariable[]" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a list of objects representing the user-defined variables within a project." + ] + }, + "post": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + } + ], + "operationId": "create-projects-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectVariableCreateInput" + } + } + } + }, + "tags": [ + "Project Variables" + ], + "summary": "Add a project variable", + "description": "Add a variable to a project. The `value` can be either a string or a JSON\nobject (default: string), as specified by the `is_json` boolean flag.\nSee the [Variables](https://docs.upsun.com/anchors/variables/set/project/create/)\nsection in our documentation for more information.\n", + "x-property-id-kebab": "create-projects-variables", + "x-tag-id-kebab": "Project-Variables", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Add a variable to a project. The `value` can be either a string or a JSON object (default: string), as specified", + "by the `is_json` boolean flag. See the [Variables](https://docs.upsun.com/anchors/variables/set/project/create/)", + "section in our documentation for more information." + ] + } + }, + "/projects/{projectId}/variables/{projectVariableId}": { + "get": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectVariableId" + } + ], + "operationId": "get-projects-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectVariable" + } + } + } + } + }, + "tags": [ + "Project Variables" + ], + "summary": "Get a project variable", + "description": "Retrieve a single user-defined project variable.", + "x-property-id-kebab": "get-projects-variables", + "x-tag-id-kebab": "Project-Variables", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\ProjectVariable" + ], + "x-return-types-union": "\\Upsun\\Model\\ProjectVariable", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ProjectVariable" + }, + "x-returnable": true, + "x-description": [ + "Retrieve a single user-defined project variable." + ] + }, + "patch": { + "requestBody": { + "description": "", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectVariablePatch" + } + } + } + }, + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectVariableId" + } + ], + "operationId": "update-projects-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Project Variables" + ], + "summary": "Update a project variable", + "description": "Update a single user-defined project variable.\nThe `value` can be either a string or a JSON\nobject (default: string), as specified by the `is_json` boolean flag.\nSee the [Variables](https://docs.upsun.com/anchors/variables/set/project/create/)\nsection in our documentation for more information.\n", + "x-property-id-kebab": "update-projects-variables", + "x-tag-id-kebab": "Project-Variables", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update a single user-defined project variable. The `value` can be either a string or a JSON object (default:", + "string), as specified by the `is_json` boolean flag. See the", + "[Variables](https://docs.upsun.com/anchors/variables/set/project/create/) section in our documentation for more", + "information." + ] + }, + "delete": { + "parameters": [ + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectId" + }, + { + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "name": "projectVariableId" + } + ], + "operationId": "delete-projects-variables", + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Project Variables" + ], + "summary": "Delete a project variable", + "description": "Delete a single user-defined project variable.", + "x-property-id-kebab": "delete-projects-variables", + "x-tag-id-kebab": "Project-Variables", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Delete a single user-defined project variable." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/autoscaling/settings": { + "get": { + "tags": [ + "Autoscaling" + ], + "description": "Retrieves Autoscaler settings", + "operationId": "get-autoscaler-settings", + "parameters": [ + { + "name": "projectId", + "in": "path", + "description": "A string that uniquely identifies the project", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "environmentId", + "in": "path", + "description": "A string that uniquely identifies the project environment", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "default": { + "description": "Autoscaler settings", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AutoscalerSettings" + } + } + } + } + }, + "summary": "Retrieves Autoscaler settings", + "x-property-id-kebab": "get-autoscaler-settings", + "x-tag-id-kebab": "Autoscaling", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AutoscalerSettings" + ], + "x-return-types-union": "\\Upsun\\Model\\AutoscalerSettings", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AutoscalerSettings" + }, + "x-returnable": true, + "x-description": [ + "Retrieves Autoscaler settings" + ] + }, + "post": { + "tags": [ + "Autoscaling" + ], + "description": "Updates Autoscaler settings", + "operationId": "post-autoscaler-settings", + "parameters": [ + { + "name": "projectId", + "in": "path", + "description": "A string that uniquely identifies the project", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "environmentId", + "in": "path", + "description": "A string that uniquely identifies the project environment", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "Settings to update", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AutoscalerSettings" + } + } + } + }, + "responses": { + "200": { + "description": "Updated Autoscaler settings", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AutoscalerSettings" + } + } + } + } + }, + "summary": "Updates Autoscaler settings", + "x-property-id-kebab": "post-autoscaler-settings", + "x-tag-id-kebab": "Autoscaling", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AutoscalerSettings" + ], + "x-return-types-union": "\\Upsun\\Model\\AutoscalerSettings", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AutoscalerSettings" + }, + "x-returnable": true, + "x-description": [ + "Updates Autoscaler settings" + ] + }, + "patch": { + "tags": [ + "Autoscaling" + ], + "description": "Modifies Autoscaler settings", + "operationId": "patch-autoscaler-settings", + "parameters": [ + { + "name": "projectId", + "in": "path", + "description": "A string that uniquely identifies the project", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "environmentId", + "in": "path", + "description": "A string that uniquely identifies the project environment", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "Settings to modify", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AutoscalerSettings" + } + } + } + }, + "responses": { + "200": { + "description": "Updated Autoscaler settings", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AutoscalerSettings" + } + } + } + } + }, + "summary": "Modifies Autoscaler settings", + "x-property-id-kebab": "patch-autoscaler-settings", + "x-tag-id-kebab": "Autoscaling", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AutoscalerSettings" + ], + "x-return-types-union": "\\Upsun\\Model\\AutoscalerSettings", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AutoscalerSettings" + }, + "x-returnable": true, + "x-description": [ + "Modifies Autoscaler settings" + ] + } + }, + "/ref/organizations": { + "get": { + "summary": "List referenced organizations", + "description": "Retrieves a list of organizations referenced by a trusted service. Clients cannot construct the URL themselves. The correct URL will be provided in the HAL links of another API response, in the _links object with a key like ref:organizations:0.", + "operationId": "list-referenced-orgs", + "tags": [ + "References" + ], + "parameters": [ + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "in", + "description": "The list of comma-separated organization IDs generated by a trusted service.", + "required": true + }, + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "sig", + "description": "The signature of this request generated by a trusted service.", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "A map of referenced organizations indexed by the organization ID.", + "additionalProperties": { + "$ref": "#/components/schemas/OrganizationReference" + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-referenced-orgs", + "x-tag-id-kebab": "References", + "x-return-types-displayReturn": true, + "x-return-types": [ + "array" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "array" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of organizations referenced by a trusted service. Clients cannot construct the URL themselves.", + "The correct URL will be provided in the HAL links of another API response, in the _links object with", + "a key like ref:organizations:0." + ] + } + }, + "/users/{user_id}/organizations": { + "get": { + "summary": "User organizations", + "description": "Retrieves organizations that the specified user is a member of.", + "operationId": "list-user-orgs", + "tags": [ + "Organizations" + ], + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + }, + { + "in": "query", + "name": "filter[id]", + "description": "Allows filtering by `id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[type]", + "description": "Allows filtering by `type` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[vendor]", + "description": "Allows filtering by `vendor` using one or more operators.\n", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[status]", + "description": "Allows filtering by `status` using one or more operators.
\nDefaults to `filter[status][in]=active,restricted,suspended`.\n", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[updated_at]", + "description": "Allows filtering by `updated_at` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/DateTimeFilter" + } + }, + { + "in": "query", + "name": "page[size]", + "description": "Determines the number of items to show.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": null + } + }, + { + "in": "query", + "name": "page[before]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page[after]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `name`, `label`, `created_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Organization" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-user-orgs", + "x-tag-id-kebab": "Organizations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves organizations that the specified user is a member of." + ] + } + }, + "/organizations": { + "get": { + "summary": "List organizations", + "description": "Non-admin users will only see organizations they are members of.", + "operationId": "list-orgs", + "tags": [ + "Organizations" + ], + "parameters": [ + { + "in": "query", + "name": "filter[id]", + "description": "Allows filtering by `id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[type]", + "description": "Allows filtering by `type` using one or more operators.\n", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[owner_id]", + "description": "Allows filtering by `owner_id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[name]", + "description": "Allows filtering by `name` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[label]", + "description": "Allows filtering by `label` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[vendor]", + "description": "Allows filtering by `vendor` using one or more operators.\n", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[capabilities]", + "description": "Allows filtering by `capabilites` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/ArrayFilter" + } + }, + { + "in": "query", + "name": "filter[status]", + "description": "Allows filtering by `status` using one or more operators.
\nDefaults to `filter[status][in]=active,restricted,suspended`.\n", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[updated_at]", + "description": "Allows filtering by `updated_at` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/DateTimeFilter" + } + }, + { + "in": "query", + "name": "page[size]", + "description": "Determines the number of items to show.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": null + } + }, + { + "in": "query", + "name": "page[before]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page[after]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `name`, `label`, `created_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Total number of items across pages." + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Organization" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-orgs", + "x-tag-id-kebab": "Organizations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Non-admin users will only see organizations they are members of." + ] + }, + "post": { + "summary": "Create organization", + "description": "Creates a new organization.", + "operationId": "create-org", + "tags": [ + "Organizations" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "label" + ], + "properties": { + "type": { + "type": "string", + "description": "The type of the organization.", + "enum": [ + "fixed", + "flexible" + ] + }, + "owner_id": { + "type": "string", + "format": "uuid", + "description": "ID of the owner." + }, + "name": { + "type": "string", + "description": "A unique machine name representing the organization." + }, + "label": { + "type": "string", + "description": "The human-readable label of the organization." + }, + "country": { + "type": "string", + "description": "The organization country (2-letter country code).", + "maxLength": 2 + }, + "security_contact": { + "type": "string", + "format": "email", + "description": "The security contact email address for the organization." + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Organization" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "create-org", + "x-tag-id-kebab": "Organizations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Organization" + ], + "x-return-types-union": "\\Upsun\\Model\\Organization", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Organization" + }, + "x-returnable": true, + "x-description": [ + "Creates a new organization." + ] + } + }, + "/organizations/{organization_id}": { + "get": { + "summary": "Get organization", + "description": "Retrieves the specified organization.", + "operationId": "get-org", + "tags": [ + "Organizations" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Organization" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-org", + "x-tag-id-kebab": "Organizations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Organization" + ], + "x-return-types-union": "\\Upsun\\Model\\Organization", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Organization" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the specified organization." + ] + }, + "patch": { + "summary": "Update organization", + "description": "Updates the specified organization.", + "operationId": "update-org", + "tags": [ + "Organizations" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "A unique machine name representing the organization." + }, + "label": { + "type": "string", + "description": "The human-readable label of the organization." + }, + "country": { + "type": "string", + "description": "The organization country (2-letter country code).", + "maxLength": 2 + }, + "security_contact": { + "type": "string", + "format": "email", + "description": "The security contact email address for the organization." + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Organization" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "update-org", + "x-tag-id-kebab": "Organizations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Organization" + ], + "x-return-types-union": "\\Upsun\\Model\\Organization", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Organization" + }, + "x-returnable": true, + "x-description": [ + "Updates the specified organization." + ] + }, + "delete": { + "summary": "Delete organization", + "description": "Deletes the specified organization.", + "operationId": "delete-org", + "tags": [ + "Organizations" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "delete-org", + "x-tag-id-kebab": "Organizations", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Deletes the specified organization." + ] + } + }, + "/organizations/{organization_id}/mfa-enforcement": { + "get": { + "summary": "Get organization MFA settings", + "description": "Retrieves MFA settings for the specified organization.", + "operationId": "get-org-mfa-enforcement", + "tags": [ + "Mfa" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationMfaEnforcement" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-org-mfa-enforcement", + "x-tag-id-kebab": "Mfa", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationMfaEnforcement" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationMfaEnforcement", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationMfaEnforcement" + }, + "x-returnable": true, + "x-description": [ + "Retrieves MFA settings for the specified organization." + ] + } + }, + "/organizations/{organization_id}/mfa-enforcement/enable": { + "post": { + "summary": "Enable organization MFA enforcement", + "description": "Enables MFA enforcement for the specified organization.", + "operationId": "enable-org-mfa-enforcement", + "tags": [ + "Mfa" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "enable-org-mfa-enforcement", + "x-tag-id-kebab": "Mfa", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Enables MFA enforcement for the specified organization." + ] + } + }, + "/organizations/{organization_id}/mfa-enforcement/disable": { + "post": { + "summary": "Disable organization MFA enforcement", + "description": "Disables MFA enforcement for the specified organization.", + "operationId": "disable-org-mfa-enforcement", + "tags": [ + "Mfa" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "disable-org-mfa-enforcement", + "x-tag-id-kebab": "Mfa", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Disables MFA enforcement for the specified organization." + ] + } + }, + "/organizations/{organization_id}/mfa/remind": { + "post": { + "summary": "Send MFA reminders to organization members", + "description": "Sends a reminder about setting up MFA to the specified organization members.", + "operationId": "send-org-mfa-reminders", + "tags": [ + "Mfa" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "user_ids": { + "type": "array", + "description": "The organization members.", + "items": { + "type": "string", + "format": "uuid", + "description": "The ID of the user." + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "An HTTP-like status code referring to the result of the operation for the specific user." + }, + "message": { + "type": "string", + "description": "A human-readable message describing the result of the operation for the specific user" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "send-org-mfa-reminders", + "x-tag-id-kebab": "Mfa", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": { + "return": true + }, + "x-returnable": true, + "x-description": [ + "Sends a reminder about setting up MFA to the specified organization members." + ] + } + }, + "/organizations/{organization_id}/members": { + "get": { + "summary": "List organization members", + "description": "Accessible to organization owners and members with the \"manage members\" permission.", + "operationId": "list-org-members", + "tags": [ + "Organization Members" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "in": "query", + "name": "filter[permissions]", + "description": "Allows filtering by `permissions` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/ArrayFilter" + } + }, + { + "in": "query", + "name": "page[size]", + "description": "Determines the number of items to show.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": null + } + }, + { + "in": "query", + "name": "page[before]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page[after]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `created_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Total number of items across pages." + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrganizationMember" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-org-members", + "x-tag-id-kebab": "Organization-Members", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Accessible to organization owners and members with the \"manage members\" permission." + ] + }, + "post": { + "summary": "Create organization member", + "description": "Creates a new organization member.", + "operationId": "create-org-member", + "tags": [ + "Organization Members" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "user_id" + ], + "properties": { + "user_id": { + "type": "string", + "format": "uuid", + "description": "ID of the user." + }, + "permissions": { + "$ref": "#/components/schemas/Permissions" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationMember" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "create-org-member", + "x-tag-id-kebab": "Organization-Members", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationMember" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationMember", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationMember" + }, + "x-returnable": true, + "x-description": [ + "Creates a new organization member." + ] + } + }, + "/organizations/{organization_id}/members/{user_id}": { + "get": { + "summary": "Get organization member", + "description": "Retrieves the specified organization member.", + "operationId": "get-org-member", + "tags": [ + "Organization Members" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "$ref": "#/components/parameters/UserID" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationMember" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-org-member", + "x-tag-id-kebab": "Organization-Members", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationMember" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationMember", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationMember" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the specified organization member." + ] + }, + "patch": { + "summary": "Update organization member", + "description": "Updates the specified organization member.", + "operationId": "update-org-member", + "tags": [ + "Organization Members" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/UserID" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "permissions": { + "$ref": "#/components/schemas/Permissions" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationMember" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "update-org-member", + "x-tag-id-kebab": "Organization-Members", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationMember" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationMember", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationMember" + }, + "x-returnable": true, + "x-description": [ + "Updates the specified organization member." + ] + }, + "delete": { + "summary": "Delete organization member", + "description": "Deletes the specified organization member.", + "operationId": "delete-org-member", + "tags": [ + "Organization Members" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/UserID" + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "delete-org-member", + "x-tag-id-kebab": "Organization-Members", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Deletes the specified organization member." + ] + } + }, + "/organizations/{organization_id}/address": { + "get": { + "summary": "Get address", + "description": "Retrieves the address for the specified organization.", + "operationId": "get-org-address", + "tags": [ + "Profiles" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Address" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-org-address", + "x-tag-id-kebab": "Profiles", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Address" + ], + "x-return-types-union": "\\Upsun\\Model\\Address", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Address" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the address for the specified organization." + ] + }, + "patch": { + "summary": "Update address", + "description": "Updates the address for the specified organization.", + "operationId": "update-org-address", + "tags": [ + "Profiles" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Address" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Address" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "update-org-address", + "x-tag-id-kebab": "Profiles", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Address" + ], + "x-return-types-union": "\\Upsun\\Model\\Address", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Address" + }, + "x-returnable": true, + "x-description": [ + "Updates the address for the specified organization." + ] + } + }, + "/organizations/{organization_id}/invoices": { + "get": { + "summary": "List invoices", + "description": "Retrieves a list of invoices for the specified organization.", + "operationId": "list-org-invoices", + "tags": [ + "Invoices" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "$ref": "#/components/parameters/filter_invoice_status" + }, + { + "$ref": "#/components/parameters/filter_invoice_type" + }, + { + "$ref": "#/components/parameters/filter_order_id" + }, + { + "$ref": "#/components/parameters/page" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Invoice" + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-org-invoices", + "x-tag-id-kebab": "Invoices", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of invoices for the specified organization." + ] + } + }, + "/organizations/{organization_id}/invoices/{invoice_id}": { + "get": { + "summary": "Get invoice", + "description": "Retrieves an invoice for the specified organization.", + "operationId": "get-org-invoice", + "tags": [ + "Invoices" + ], + "parameters": [ + { + "$ref": "#/components/parameters/InvoiceID" + }, + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Invoice" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-org-invoice", + "x-tag-id-kebab": "Invoices", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Invoice" + ], + "x-return-types-union": "\\Upsun\\Model\\Invoice", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Invoice" + }, + "x-returnable": true, + "x-description": [ + "Retrieves an invoice for the specified organization." + ] + } + }, + "/organizations/{organization_id}/profile": { + "get": { + "summary": "Get profile", + "description": "Retrieves the profile for the specified organization.", + "operationId": "get-org-profile", + "tags": [ + "Profiles" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Profile" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-org-profile", + "x-tag-id-kebab": "Profiles", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Profile" + ], + "x-return-types-union": "\\Upsun\\Model\\Profile", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Profile" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the profile for the specified organization." + ] + }, + "patch": { + "summary": "Update profile", + "description": "Updates the profile for the specified organization.", + "operationId": "update-org-profile", + "tags": [ + "Profiles" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "default_catalog": { + "type": "string", + "description": "The URL of a catalog file which overrides the default." + }, + "project_options_url": { + "type": "string", + "format": "uri", + "description": "The URL of an organization-wide project options file." + }, + "company_name": { + "type": "string", + "description": "The company name." + }, + "customer_type": { + "type": "string", + "description": "The customer type of this account.", + "enum": [ + "indvidual", + "company", + "government" + ] + }, + "vat_number": { + "type": "string", + "description": "The VAT number of the company." + }, + "billing_contact": { + "type": "string", + "format": "email", + "description": "The e-mail address of a contact to whom billing notices will be sent." + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Profile" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "update-org-profile", + "x-tag-id-kebab": "Profiles", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Profile" + ], + "x-return-types-union": "\\Upsun\\Model\\Profile", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Profile" + }, + "x-returnable": true, + "x-description": [ + "Updates the profile for the specified organization." + ] + } + }, + "/organizations/{organization_id}/orders": { + "get": { + "summary": "List orders", + "description": "Retrieves orders for the specified organization.", + "operationId": "list-org-orders", + "tags": [ + "Orders" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "$ref": "#/components/parameters/filter_order_status" + }, + { + "$ref": "#/components/parameters/filter_order_total" + }, + { + "$ref": "#/components/parameters/page" + }, + { + "$ref": "#/components/parameters/mode" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Order" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-org-orders", + "x-tag-id-kebab": "Orders", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves orders for the specified organization." + ] + } + }, + "/organizations/{organization_id}/orders/{order_id}": { + "get": { + "summary": "Get order", + "description": "Retrieves an order for the specified organization.", + "operationId": "get-org-order", + "tags": [ + "Orders" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "$ref": "#/components/parameters/OrderID" + }, + { + "$ref": "#/components/parameters/mode" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-org-order", + "x-tag-id-kebab": "Orders", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Order" + ], + "x-return-types-union": "\\Upsun\\Model\\Order", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Order" + }, + "x-returnable": true, + "x-description": [ + "Retrieves an order for the specified organization." + ] + } + }, + "/organizations/{organization_id}/orders/{order_id}/authorize": { + "post": { + "summary": "Create confirmation credentials for for 3D-Secure", + "description": "Creates confirmation credentials for payments that require online authorization", + "operationId": "create-authorization-credentials", + "tags": [ + "Orders" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "$ref": "#/components/parameters/OrderID" + } + ], + "responses": { + "200": { + "description": "Payment authorization credentials, if the payment is pending", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "redirect_to_url": { + "type": "object", + "description": "URL information to complete the payment.", + "properties": { + "return_url": { + "type": "string", + "description": "Return URL after payment completion." + }, + "url": { + "type": "string", + "description": "URL for payment finalization." + } + } + }, + "type": { + "type": "string", + "description": "Required payment action type." + } + } + } + } + } + }, + "400": { + "description": "Bad Request when no authorization is required.", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "create-authorization-credentials", + "x-tag-id-kebab": "Orders", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Creates confirmation credentials for payments that require online authorization" + ] + } + }, + "/organizations/{organization_id}/records/plan": { + "get": { + "summary": "List plan records", + "description": "Retrieves plan records for the specified organization.", + "operationId": "list-org-plan-records", + "tags": [ + "Records" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "$ref": "#/components/parameters/filter_subscription_id" + }, + { + "$ref": "#/components/parameters/filter_subscription_plan" + }, + { + "$ref": "#/components/parameters/record_status" + }, + { + "$ref": "#/components/parameters/record_start" + }, + { + "$ref": "#/components/parameters/record_end" + }, + { + "$ref": "#/components/parameters/record_started_at" + }, + { + "$ref": "#/components/parameters/record_ended_at" + }, + { + "$ref": "#/components/parameters/page" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlanRecords" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-org-plan-records", + "x-tag-id-kebab": "Records", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves plan records for the specified organization." + ] + } + }, + "/organizations/{organization_id}/records/usage": { + "get": { + "summary": "List usage records", + "description": "Retrieves usage records for the specified organization.", + "operationId": "list-org-usage-records", + "tags": [ + "Records" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "$ref": "#/components/parameters/filter_subscription_id" + }, + { + "$ref": "#/components/parameters/record_usage_group" + }, + { + "$ref": "#/components/parameters/record_start" + }, + { + "$ref": "#/components/parameters/record_started_at" + }, + { + "$ref": "#/components/parameters/page" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Usage" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-org-usage-records", + "x-tag-id-kebab": "Records", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves usage records for the specified organization." + ] + } + }, + "/organizations/{organization_id}/subscriptions/estimate": { + "get": { + "summary": "Estimate the price of a new subscription", + "operationId": "estimate-new-org-subscription", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "in": "query", + "name": "plan", + "description": "The plan type of the subscription.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "environments", + "description": "The maximum number of environments which can be provisioned on the project.", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "in": "query", + "name": "storage", + "description": "The total storage available to each environment, in MiB.", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "in": "query", + "name": "user_licenses", + "description": "The number of user licenses.", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "in": "query", + "name": "format", + "description": "The format of the estimation output.", + "required": false, + "schema": { + "type": "string", + "enum": [ + "formatted", + "complex" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EstimationObject" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "estimate-new-org-subscription", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\EstimationObject" + ], + "x-return-types-union": "\\Upsun\\Model\\EstimationObject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\EstimationObject" + }, + "x-returnable": true + } + }, + "/organizations/{organization_id}/subscriptions/can-create": { + "get": { + "summary": "Checks if the user is able to create a new project.", + "operationId": "can-create-new-org-subscription", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "properties": { + "can_create": { + "description": "Boolean result of the check.", + "type": "boolean" + }, + "message": { + "description": "Details in case of negative check result.", + "type": "string" + }, + "required_action": { + "description": "Required action impending project creation.", + "type": "object", + "nullable": true, + "properties": { + "action": { + "description": "Machine readable definition of requirement.", + "type": "string" + }, + "type": { + "description": "Specification of the type of action.", + "type": "string" + } + } + } + }, + "type": "object" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "can-create-new-org-subscription", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true + } + }, + "/organizations/{organization_id}/subscriptions/{subscription_id}/estimate": { + "get": { + "summary": "Estimate the price of a subscription", + "operationId": "estimate-org-subscription", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/SubscriptionID" + }, + { + "in": "query", + "name": "plan", + "description": "The plan type of the subscription.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "environments", + "description": "The maximum number of environments which can be provisioned on the project.", + "schema": { + "type": "integer" + } + }, + { + "in": "query", + "name": "storage", + "description": "The total storage available to each environment, in MiB.", + "schema": { + "type": "integer" + } + }, + { + "in": "query", + "name": "user_licenses", + "description": "The number of user licenses.", + "schema": { + "type": "integer" + } + }, + { + "in": "query", + "name": "format", + "description": "The format of the estimation output.", + "schema": { + "type": "string", + "enum": [ + "formatted", + "complex" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EstimationObject" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "estimate-org-subscription", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\EstimationObject" + ], + "x-return-types-union": "\\Upsun\\Model\\EstimationObject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\EstimationObject" + }, + "x-returnable": true + } + }, + "/organizations/{organization_id}/subscriptions/{subscription_id}/current_usage": { + "get": { + "summary": "Get current usage for a subscription", + "operationId": "get-org-subscription-current-usage", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/SubscriptionID" + }, + { + "in": "query", + "name": "usage_groups", + "description": "A list of usage groups to retrieve current usage for.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "include_not_charged", + "description": "Whether to include not charged usage groups.", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionCurrentUsageObject" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-org-subscription-current-usage", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\SubscriptionCurrentUsageObject" + ], + "x-return-types-union": "\\Upsun\\Model\\SubscriptionCurrentUsageObject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\SubscriptionCurrentUsageObject" + }, + "x-returnable": true + } + }, + "/organizations/{organization_id}/subscriptions/{subscription_id}/addons": { + "get": { + "summary": "List addons for a subscription", + "operationId": "list-subscription-addons", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/SubscriptionID" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionAddonsObject" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "list-subscription-addons", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\SubscriptionAddonsObject" + ], + "x-return-types-union": "\\Upsun\\Model\\SubscriptionAddonsObject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\SubscriptionAddonsObject" + }, + "x-returnable": true + } + }, + "/organizations/{organization_id}/vouchers": { + "get": { + "summary": "List vouchers", + "description": "Retrieves vouchers for the specified organization.", + "operationId": "list-org-vouchers", + "tags": [ + "Vouchers" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vouchers" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "list-org-vouchers", + "x-tag-id-kebab": "Vouchers", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Vouchers" + ], + "x-return-types-union": "\\Upsun\\Model\\Vouchers", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Vouchers" + }, + "x-returnable": true, + "x-description": [ + "Retrieves vouchers for the specified organization." + ] + } + }, + "/organizations/{organization_id}/vouchers/apply": { + "post": { + "summary": "Apply voucher", + "description": "Applies a voucher for the specified organization, and refreshes the currently open order.", + "operationId": "apply-org-voucher", + "tags": [ + "Vouchers" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "code" + ], + "properties": { + "code": { + "type": "string", + "description": "The voucher code." + } + } + } + } + } + }, + "responses": { + "204": { + "description": "No Content" + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "apply-org-voucher", + "x-tag-id-kebab": "Vouchers", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Applies a voucher for the specified organization, and refreshes the currently open order." + ] + } + }, + "/organizations/{organization_id}/estimate": { + "get": { + "summary": "Estimate total spend", + "description": "Estimates the total spend for the specified organization.", + "operationId": "estimate-org", + "tags": [ + "Organization Management" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationEstimationObject" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "estimate-org", + "x-tag-id-kebab": "Organization-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationEstimationObject" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationEstimationObject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationEstimationObject" + }, + "x-returnable": true, + "x-description": [ + "Estimates the total spend for the specified organization." + ] + } + }, + "/organizations/{organization_id}/addons": { + "get": { + "summary": "Get add-ons", + "description": "Retrieves information about the add-ons for an organization.", + "operationId": "get-org-addons", + "tags": [ + "Add-ons" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationAddonsObject" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "get-org-addons", + "x-tag-id-kebab": "Add-ons", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationAddonsObject" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationAddonsObject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationAddonsObject" + }, + "x-returnable": true, + "x-description": [ + "Retrieves information about the add-ons for an organization." + ] + }, + "patch": { + "summary": "Update organization add-ons", + "description": "Updates the add-ons configuration for an organization.", + "operationId": "update-org-addons", + "tags": [ + "Add-ons" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "user_management": { + "type": "string", + "description": "The user management level to apply.", + "enum": [ + "standard", + "enhanced" + ], + "example": "standard" + }, + "support_level": { + "type": "string", + "description": "The support level to apply.", + "enum": [ + "basic", + "premium" + ], + "example": "basic" + } + }, + "additionalProperties": false, + "minProperties": 1 + } + } + } + }, + "responses": { + "200": { + "description": "Add-ons updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationAddonsObject" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "update-org-addons", + "x-tag-id-kebab": "Add-ons", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationAddonsObject" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationAddonsObject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationAddonsObject" + }, + "x-returnable": true, + "x-description": [ + "Updates the add-ons configuration for an organization." + ] + } + }, + "/organizations/{organization_id}/alerts/billing": { + "get": { + "summary": "Get billing alert configuration", + "description": "Retrieves billing alert configuration for the specified organization.", + "operationId": "get-org-billing-alert-config", + "tags": [ + "Organization Management" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationAlertConfig" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "get-org-billing-alert-config", + "x-tag-id-kebab": "Organization-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationAlertConfig" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationAlertConfig", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationAlertConfig" + }, + "x-returnable": true, + "x-description": [ + "Retrieves billing alert configuration for the specified organization." + ] + }, + "patch": { + "summary": "Update billing alert configuration", + "description": "Updates billing alert configuration for the specified organization.", + "operationId": "update-org-billing-alert-config", + "tags": [ + "Organization Management" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "active": { + "type": "boolean", + "description": "Whether the billing alert should be active or not." + }, + "config": { + "type": "object", + "description": "The configuration for billing alerts.", + "properties": { + "threshold": { + "type": "integer", + "description": "The amount after which a billing alert should be triggered." + }, + "mode": { + "type": "string", + "description": "The mode in which the alert is triggered." + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationAlertConfig" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "update-org-billing-alert-config", + "x-tag-id-kebab": "Organization-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationAlertConfig" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationAlertConfig", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationAlertConfig" + }, + "x-returnable": true, + "x-description": [ + "Updates billing alert configuration for the specified organization." + ] + } + }, + "/organizations/{organization_id}/alerts/subscriptions/{subscription_id}/usage": { + "get": { + "summary": "Get usage alerts", + "description": "Retrieves current and available usage alerts.", + "operationId": "get-subscription-usage-alerts", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "$ref": "#/components/parameters/SubscriptionID" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "current": { + "type": "array", + "description": "The list of currently set usage alerts.", + "items": { + "$ref": "#/components/schemas/UsageAlert" + } + }, + "available": { + "type": "array", + "description": "The list of available usage alerts.", + "items": { + "$ref": "#/components/schemas/UsageAlert" + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "get-subscription-usage-alerts", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves current and available usage alerts." + ] + }, + "patch": { + "summary": "Update usage alerts.", + "description": "Updates usage alerts for a subscription.", + "operationId": "update-subscription-usage-alerts", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + }, + { + "$ref": "#/components/parameters/SubscriptionID" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "alerts": { + "type": "array", + "description": "The list of alerts to update.", + "items": { + "type": "object", + "description": "An alert object.", + "properties": { + "id": { + "type": "string", + "description": "The usage alert identifier." + }, + "active": { + "type": "boolean", + "description": "Whether the alert is activated." + }, + "config": { + "type": "object", + "description": "The configuration for the usage alerts.", + "properties": { + "threshold": { + "type": "integer", + "description": "The amount after which an alert should be triggered." + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "current": { + "type": "array", + "description": "The list of currently set usage alerts.", + "items": { + "$ref": "#/components/schemas/UsageAlert" + } + }, + "available": { + "type": "array", + "description": "The list of available usage alerts.", + "items": { + "$ref": "#/components/schemas/UsageAlert" + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-property-id-kebab": "update-subscription-usage-alerts", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Updates usage alerts for a subscription." + ] + } + }, + "/organizations/{organization_id}/discounts": { + "get": { + "summary": "List organization discounts", + "description": "Retrieves all applicable discounts granted to the specified organization.", + "operationId": "list-org-discounts", + "tags": [ + "Discounts" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationIDName" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Discount" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "list-org-discounts", + "x-tag-id-kebab": "Discounts", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves all applicable discounts granted to the specified organization." + ] + } + }, + "/organizations/{organization_id}/prepayment": { + "get": { + "summary": "Get organization prepayment information", + "description": "Retrieves prepayment information for the specified organization, if applicable.", + "operationId": "get-org-prepayment-info", + "tags": [ + "Organization Management" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "prepayment": { + "$ref": "#/components/schemas/PrepaymentObject" + }, + "_links": { + "type": "object", + "properties": { + "self": { + "type": "object", + "description": "Link to the current resource.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link." + } + } + }, + "transactions": { + "type": "object", + "description": "Link to the prepayment transactions resource.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link." + } + } + } + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "get-org-prepayment-info", + "x-tag-id-kebab": "Organization-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves prepayment information for the specified organization, if applicable." + ] + } + }, + "/organizations/{organization_id}/prepayment/transactions": { + "get": { + "summary": "List organization prepayment transactions", + "description": "Retrieves a list of prepayment transactions for the specified organization, if applicable.", + "operationId": "list-org-prepayment-transactions", + "tags": [ + "Organization Management" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Total number of items across pages." + }, + "transactions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PrepaymentTransactionObject" + } + }, + "_links": { + "type": "object", + "properties": { + "self": { + "type": "object", + "description": "Link to the current set of items.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link." + } + } + }, + "previous": { + "type": "object", + "description": "Link to the previous set of items.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link." + } + } + }, + "next": { + "type": "object", + "description": "Link to the next set of items.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link" + } + } + }, + "prepayment": { + "type": "object", + "description": "Link to the prepayment resource.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link." + } + } + } + } + } + } + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "x-vendor": "upsun", + "x-property-id-kebab": "list-org-prepayment-transactions", + "x-tag-id-kebab": "Organization-Management", + "x-return-types-displayReturn": false, + "x-return-types": [ + "object" + ], + "x-phpdoc": { + "return": "object" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of prepayment transactions for the specified organization, if applicable." + ] + } + }, + "/organizations/{organization_id}/projects": { + "get": { + "summary": "List projects", + "description": "Retrieves a list of projects for the specified organization.", + "operationId": "list-org-projects", + "tags": [ + "Organization Projects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "in": "query", + "name": "filter[id]", + "description": "Allows filtering by `id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[title]", + "description": "Allows filtering by `title` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[status]", + "description": "Allows filtering by `status` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "$ref": "#/components/parameters/FilterUpdatedAt" + }, + { + "$ref": "#/components/parameters/FilterCreatedAt" + }, + { + "$ref": "#/components/parameters/PageSize" + }, + { + "$ref": "#/components/parameters/PageBefore" + }, + { + "$ref": "#/components/parameters/PageAfter" + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `id`, `region`, `title`, `type`, `plan`, `status`, `created_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Total number of items across pages." + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrganizationProject" + } + }, + "facets": { + "$ref": "#/components/schemas/ProjectFacets" + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "list-org-projects", + "x-tag-id-kebab": "Organization-Projects", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": {}, + "x-returnable": true, + "x-description": [ + "Retrieves a list of projects for the specified organization." + ] + }, + "post": { + "summary": "Create project", + "description": "Creates a new project in the specified organization.", + "operationId": "create-org-project", + "tags": [ + "Organization Projects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "region" + ], + "properties": { + "organization_id": { + "$ref": "#/components/schemas/OrganizationID" + }, + "region": { + "$ref": "#/components/schemas/RegionID" + }, + "title": { + "$ref": "#/components/schemas/ProjectTitle" + }, + "type": { + "$ref": "#/components/schemas/ProjectType" + }, + "plan": { + "$ref": "#/components/schemas/ProjectPlan" + }, + "default_branch": { + "$ref": "#/components/schemas/ProjectDefaultBranch" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationProject" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + } + }, + "x-property-id-kebab": "create-org-project", + "x-tag-id-kebab": "Organization-Projects", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationProject" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationProject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationProject" + }, + "x-returnable": true, + "x-description": [ + "Creates a new project in the specified organization." + ] + } + }, + "/organizations/{organization_id}/projects/{project_id}": { + "get": { + "summary": "Get project", + "description": "Retrieves the specified project.", + "operationId": "get-org-project", + "tags": [ + "Organization Projects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/ProjectID" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationProject" + } + } + } + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "get-org-project", + "x-tag-id-kebab": "Organization-Projects", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationProject" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationProject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationProject" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the specified project." + ] + }, + "patch": { + "summary": "Update project", + "description": "Updates the specified project.", + "operationId": "update-org-project", + "tags": [ + "Organization Projects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/ProjectID" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "$ref": "#/components/schemas/ProjectTitle" + }, + "plan": { + "$ref": "#/components/schemas/ProjectPlan" + }, + "timezone": { + "$ref": "#/components/schemas/ProjectTimeZone" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationProject" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + } + }, + "x-property-id-kebab": "update-org-project", + "x-tag-id-kebab": "Organization-Projects", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationProject" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationProject", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationProject" + }, + "x-returnable": true, + "x-description": [ + "Updates the specified project." + ] + }, + "delete": { + "summary": "Delete project", + "description": "Deletes the specified project.", + "operationId": "delete-org-project", + "tags": [ + "Organization Projects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/ProjectID" + } + ], + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + } + }, + "x-property-id-kebab": "delete-org-project", + "x-tag-id-kebab": "Organization-Projects", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Deletes the specified project." + ] + } + }, + "/organizations/{organization_id}/metrics/carbon": { + "get": { + "summary": "Query project carbon emissions metrics for an entire organization", + "description": "Queries the carbon emission data for all projects owned by the specified organiation.", + "operationId": "query-organiation-carbon", + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/TimeRangeFrom" + }, + { + "$ref": "#/components/parameters/TimeRangeTo" + }, + { + "$ref": "#/components/parameters/TimeRangeInterval" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationCarbon" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "query-organiation-carbon", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\OrganizationCarbon" + ], + "x-return-types-union": "\\Upsun\\Model\\OrganizationCarbon", + "x-phpdoc": { + "return": "\\Upsun\\Model\\OrganizationCarbon" + }, + "x-returnable": true, + "x-description": [ + "Queries the carbon emission data for all projects owned by the specified organiation." + ] + } + }, + "/organizations/{organization_id}/projects/{project_id}/metrics/carbon": { + "get": { + "summary": "Query project carbon emissions metrics", + "description": "Queries the carbon emission data for the specified project using the supplied parameters.", + "operationId": "query-project-carbon", + "tags": [ + "Organization Projects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/ProjectID" + }, + { + "$ref": "#/components/parameters/TimeRangeFrom" + }, + { + "$ref": "#/components/parameters/TimeRangeTo" + }, + { + "$ref": "#/components/parameters/TimeRangeInterval" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectCarbon" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "query-project-carbon", + "x-tag-id-kebab": "Organization-Projects", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\ProjectCarbon" + ], + "x-return-types-union": "\\Upsun\\Model\\ProjectCarbon", + "x-phpdoc": { + "return": "\\Upsun\\Model\\ProjectCarbon" + }, + "x-returnable": true, + "x-description": [ + "Queries the carbon emission data for the specified project using the supplied parameters." + ] + } + }, + "/organizations/{organization_id}/subscriptions": { + "get": { + "summary": "List subscriptions", + "description": "Retrieves subscriptions for the specified organization.", + "operationId": "list-org-subscriptions", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "name": "filter[status]", + "in": "query", + "description": "The status of the subscription. ", + "schema": { + "type": "string", + "enum": [ + "requested", + "active", + "failed", + "suspended", + "deleted" + ] + } + }, + { + "name": "filter[id]", + "in": "query", + "description": "Allows filtering by subscription `id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "name": "filter[project_id]", + "in": "query", + "description": "Allows filtering by `project_id` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "name": "filter[project_title]", + "in": "query", + "description": "Allows filtering by `project_title` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "name": "filter[region]", + "in": "query", + "description": "Allows filtering by `region` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "$ref": "#/components/parameters/FilterUpdatedAt" + }, + { + "$ref": "#/components/parameters/PageSize" + }, + { + "$ref": "#/components/parameters/PageBefore" + }, + { + "$ref": "#/components/parameters/PageAfter" + }, + { + "name": "sort", + "in": "query", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `region`, `project_title`, `type`, `plan`, `status`, `created_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Total number of items across pages." + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Subscription" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "list-org-subscriptions", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": {}, + "x-returnable": true, + "x-description": [ + "Retrieves subscriptions for the specified organization." + ] + }, + "post": { + "summary": "Create subscription", + "description": "Creates a subscription for the specified organization.", + "operationId": "create-org-subscription", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "project_region" + ], + "properties": { + "plan": { + "$ref": "#/components/schemas/ProjectPlan" + }, + "project_region": { + "type": "string", + "description": "The machine name of the region where the project is located. Cannot be changed after project creation." + }, + "project_title": { + "type": "string", + "description": "The name given to the project. Appears as the title in the UI." + }, + "options_url": { + "type": "string", + "description": "The URL of the project options file." + }, + "default_branch": { + "type": "string", + "description": "The default Git branch name for the project." + }, + "environments": { + "type": "integer", + "description": "The maximum number of active environments on the project." + }, + "storage": { + "type": "integer", + "description": "The total storage available to each environment, in MiB. Only multiples of 1024 are accepted as legal values." + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Subscription" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "create-org-subscription", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Subscription" + ], + "x-return-types-union": "\\Upsun\\Model\\Subscription", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Subscription" + }, + "x-returnable": true, + "x-description": [ + "Creates a subscription for the specified organization." + ] + } + }, + "/organizations/{organization_id}/subscriptions/{subscription_id}": { + "get": { + "summary": "Get subscription", + "description": "Retrieves a subscription for the specified organization.", + "operationId": "get-org-subscription", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/SubscriptionID" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Subscription" + } + } + } + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "get-org-subscription", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Subscription" + ], + "x-return-types-union": "\\Upsun\\Model\\Subscription", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Subscription" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a subscription for the specified organization." + ] + }, + "patch": { + "summary": "Update subscription", + "description": "Updates a subscription for the specified organization.", + "operationId": "update-org-subscription", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/SubscriptionID" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "project_title": { + "$ref": "#/components/schemas/ProjectTitle" + }, + "plan": { + "$ref": "#/components/schemas/ProjectPlan" + }, + "timezone": { + "$ref": "#/components/schemas/ProjectTimeZone" + }, + "environments": { + "type": "integer", + "description": "The maximum number of environments which can be provisioned on the project." + }, + "storage": { + "type": "integer", + "description": "The total storage available to each environment, in MiB." + }, + "big_dev": { + "type": "string", + "description": "The development environment plan." + }, + "big_dev_service": { + "type": "string", + "description": "The development service plan." + }, + "backups": { + "type": "string", + "description": "The backups plan." + }, + "observability_suite": { + "type": "string", + "description": "The observability suite option." + }, + "blackfire": { + "type": "string", + "description": "The Blackfire integration option." + }, + "continuous_profiling": { + "type": "string", + "description": "The Blackfire continuous profiling option." + }, + "project_support_level": { + "type": "string", + "description": "The project uptime option." + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Subscription" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "update-org-subscription", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Subscription" + ], + "x-return-types-union": "\\Upsun\\Model\\Subscription", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Subscription" + }, + "x-returnable": true, + "x-description": [ + "Updates a subscription for the specified organization." + ] + }, + "delete": { + "summary": "Delete subscription", + "description": "Deletes a subscription for the specified organization.", + "operationId": "delete-org-subscription", + "tags": [ + "Subscriptions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/OrganizationID" + }, + { + "$ref": "#/components/parameters/SubscriptionID" + } + ], + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "delete-org-subscription", + "x-tag-id-kebab": "Subscriptions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Deletes a subscription for the specified organization." + ] + } + }, + "/regions": { + "get": { + "summary": "List regions", + "description": "Retrieves a list of available regions.", + "operationId": "list-regions", + "tags": [ + "Regions" + ], + "parameters": [ + { + "in": "query", + "name": "filter[available]", + "description": "Allows filtering by `available` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[private]", + "description": "Allows filtering by `private` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "in": "query", + "name": "filter[zone]", + "description": "Allows filtering by `zone` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/StringFilter" + } + }, + { + "$ref": "#/components/parameters/PageSize" + }, + { + "$ref": "#/components/parameters/PageBefore" + }, + { + "$ref": "#/components/parameters/PageAfter" + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `id`, `created_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Total number of items across pages." + }, + "regions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Region" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "list-regions", + "x-tag-id-kebab": "Regions", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": {}, + "x-returnable": true, + "x-description": [ + "Retrieves a list of available regions." + ] + } + }, + "/regions/{region_id}": { + "get": { + "summary": "Get region", + "description": "Retrieves the specified region.", + "operationId": "get-region", + "tags": [ + "Regions" + ], + "parameters": [ + { + "$ref": "#/components/parameters/RegionID" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Region" + } + } + } + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "get-region", + "x-tag-id-kebab": "Regions", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\Region" + ], + "x-return-types-union": "\\Upsun\\Model\\Region", + "x-phpdoc": { + "return": "\\Upsun\\Model\\Region" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the specified region." + ] + } + }, + "/ref/projects": { + "get": { + "summary": "List referenced projects", + "description": "Retrieves a list of projects referenced by a trusted service. Clients cannot construct the URL themselves. The correct URL will be provided in the HAL links of another API response, in the _links object with a key like ref:projects:0.", + "operationId": "list-referenced-projects", + "tags": [ + "References" + ], + "parameters": [ + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "in", + "description": "The list of comma-separated project IDs generated by a trusted service.", + "required": true + }, + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "sig", + "description": "The signature of this request generated by a trusted service.", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "A map of referenced projects indexed by the organization ID.", + "additionalProperties": { + "$ref": "#/components/schemas/ProjectReference" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "list-referenced-projects", + "x-tag-id-kebab": "References", + "x-return-types-displayReturn": true, + "x-return-types": [ + "array" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "array" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of projects referenced by a trusted service. Clients cannot construct the URL themselves. The", + "correct URL will be provided in the HAL links of another API response, in the _links object with a", + "key like ref:projects:0." + ] + } + }, + "/ref/regions": { + "get": { + "summary": "List referenced regions", + "description": "Retrieves a list of regions referenced by a trusted service. Clients cannot construct the URL themselves. The correct URL will be provided in the HAL links of another API response, in the _links object with a key like ref:regions:0.", + "operationId": "list-referenced-regions", + "tags": [ + "References" + ], + "parameters": [ + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "in", + "description": "The list of comma-separated region IDs generated by a trusted service.", + "required": true + }, + { + "schema": { + "type": "string" + }, + "in": "query", + "name": "sig", + "description": "The signature of this request generated by a trusted service.", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "A map of referenced projects indexed by the organization ID.", + "additionalProperties": { + "$ref": "#/components/schemas/RegionReference" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "list-referenced-regions", + "x-tag-id-kebab": "References", + "x-return-types-displayReturn": true, + "x-return-types": [ + "array" + ], + "x-return-types-union": "array", + "x-phpdoc": { + "return": "array" + }, + "x-returnable": true, + "x-description": [ + "Retrieves a list of regions referenced by a trusted service. Clients cannot construct the URL themselves. The", + "correct URL will be provided in the HAL links of another API response, in the _links object with a", + "key like ref:regions:0." + ] + } + }, + "/projects/{project_id}/team-access": { + "parameters": [ + { + "$ref": "#/components/parameters/ProjectID" + } + ], + "get": { + "summary": "List team access for a project", + "description": "Returns a list of items representing the project access.", + "operationId": "list-project-team-access", + "tags": [ + "Team Access" + ], + "parameters": [ + { + "$ref": "#/components/parameters/PageSizeAccess" + }, + { + "$ref": "#/components/parameters/PageBefore" + }, + { + "$ref": "#/components/parameters/PageAfter" + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `granted_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TeamProjectAccess" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + }, + "x-property-id-kebab": "list-project-team-access", + "x-tag-id-kebab": "Team-Access", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": {}, + "x-returnable": true, + "x-description": [ + "Returns a list of items representing the project access." + ] + }, + "post": { + "summary": "Grant team access to a project", + "description": "Grants one or more team access to a specific project.", + "operationId": "grant-project-team-access", + "tags": [ + "Team Access" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "team_id": { + "type": "string", + "description": "ID of the team." + } + }, + "required": [ + "team_id" + ] + } + } + } + } + }, + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + }, + "x-property-id-kebab": "grant-project-team-access", + "x-tag-id-kebab": "Team-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Grants one or more team access to a specific project." + ] + } + }, + "/projects/{project_id}/team-access/{team_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/ProjectID" + }, + { + "$ref": "#/components/parameters/TeamID" + } + ], + "get": { + "summary": "Get team access for a project", + "description": "Retrieves the team's permissions for the current project.", + "operationId": "get-project-team-access", + "tags": [ + "Team Access" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TeamProjectAccess" + } + } + } + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "get-project-team-access", + "x-tag-id-kebab": "Team-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\TeamProjectAccess" + ], + "x-return-types-union": "\\Upsun\\Model\\TeamProjectAccess", + "x-phpdoc": { + "return": "\\Upsun\\Model\\TeamProjectAccess" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the team's permissions for the current project." + ] + }, + "delete": { + "summary": "Remove team access for a project", + "description": "Removes the team from the current project.", + "operationId": "remove-project-team-access", + "tags": [ + "Team Access" + ], + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "remove-project-team-access", + "x-tag-id-kebab": "Team-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Removes the team from the current project." + ] + } + }, + "/projects/{project_id}/user-access": { + "parameters": [ + { + "$ref": "#/components/parameters/ProjectID" + } + ], + "get": { + "summary": "List user access for a project", + "description": "Returns a list of items representing the project access.", + "operationId": "list-project-user-access", + "tags": [ + "User Access" + ], + "parameters": [ + { + "$ref": "#/components/parameters/PageSizeAccess" + }, + { + "$ref": "#/components/parameters/PageBefore" + }, + { + "$ref": "#/components/parameters/PageAfter" + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `granted_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UserProjectAccess" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + }, + "x-property-id-kebab": "list-project-user-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": {}, + "x-returnable": true, + "x-description": [ + "Returns a list of items representing the project access." + ] + }, + "post": { + "summary": "Grant user access to a project", + "description": "Grants one or more users access to a specific project.", + "operationId": "grant-project-user-access", + "tags": [ + "User Access" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "user_id": { + "type": "string", + "description": "ID of the user." + }, + "permissions": { + "$ref": "#/components/schemas/ProjectPermissions" + }, + "auto_add_member": { + "type": "boolean", + "description": "If the specified user is not a member of the project's organization, add it automatically." + } + }, + "additionalProperties": false, + "required": [ + "user_id", + "permissions" + ] + } + } + } + } + }, + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + }, + "x-property-id-kebab": "grant-project-user-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Grants one or more users access to a specific project." + ] + } + }, + "/projects/{project_id}/user-access/{user_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/ProjectID" + }, + { + "$ref": "#/components/parameters/UserID" + } + ], + "get": { + "summary": "Get user access for a project", + "description": "Retrieves the user's permissions for the current project.", + "operationId": "get-project-user-access", + "tags": [ + "User Access" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserProjectAccess" + } + } + } + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "get-project-user-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\UserProjectAccess" + ], + "x-return-types-union": "\\Upsun\\Model\\UserProjectAccess", + "x-phpdoc": { + "return": "\\Upsun\\Model\\UserProjectAccess" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the user's permissions for the current project." + ] + }, + "patch": { + "summary": "Update user access for a project", + "description": "Updates the user's permissions for the current project.", + "operationId": "update-project-user-access", + "tags": [ + "User Access" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "permissions" + ], + "properties": { + "permissions": { + "$ref": "#/components/schemas/ProjectPermissions" + } + } + } + } + } + }, + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "update-project-user-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Updates the user's permissions for the current project." + ] + }, + "delete": { + "summary": "Remove user access for a project", + "description": "Removes the user from the current project.", + "operationId": "remove-project-user-access", + "tags": [ + "User Access" + ], + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "remove-project-user-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Removes the user from the current project." + ] + } + }, + "/users/{user_id}/project-access": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + } + ], + "get": { + "summary": "List project access for a user", + "description": "Returns a list of items representing the user's project access.", + "operationId": "list-user-project-access", + "tags": [ + "User Access" + ], + "parameters": [ + { + "in": "query", + "name": "filter[organization_id]", + "description": "Allows filtering by `organization_id`.", + "schema": { + "type": "string" + } + }, + { + "$ref": "#/components/parameters/PageSizeAccess" + }, + { + "$ref": "#/components/parameters/PageBefore" + }, + { + "$ref": "#/components/parameters/PageAfter" + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `project_title`, `granted_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UserProjectAccess" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + }, + "x-property-id-kebab": "list-user-project-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": {}, + "x-returnable": true, + "x-description": [ + "Returns a list of items representing the user's project access." + ] + }, + "post": { + "summary": "Grant project access to a user", + "description": "Adds the user to one or more specified projects.", + "operationId": "grant-user-project-access", + "tags": [ + "User Access" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "description": "ID of the project." + }, + "permissions": { + "$ref": "#/components/schemas/ProjectPermissions" + } + }, + "additionalProperties": false, + "required": [ + "project_id", + "permissions" + ] + } + } + } + } + }, + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + }, + "x-property-id-kebab": "grant-user-project-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Adds the user to one or more specified projects." + ] + } + }, + "/users/{user_id}/project-access/{project_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/UserID" + }, + { + "$ref": "#/components/parameters/ProjectID" + } + ], + "get": { + "summary": "Get project access for a user", + "description": "Retrieves the user's permissions for the current project.", + "operationId": "get-user-project-access", + "tags": [ + "User Access" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserProjectAccess" + } + } + } + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "get-user-project-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\UserProjectAccess" + ], + "x-return-types-union": "\\Upsun\\Model\\UserProjectAccess", + "x-phpdoc": { + "return": "\\Upsun\\Model\\UserProjectAccess" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the user's permissions for the current project." + ] + }, + "patch": { + "summary": "Update project access for a user", + "description": "Updates the user's permissions for the current project.", + "operationId": "update-user-project-access", + "tags": [ + "User Access" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "permissions" + ], + "properties": { + "permissions": { + "$ref": "#/components/schemas/ProjectPermissions" + } + } + } + } + } + }, + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "update-user-project-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Updates the user's permissions for the current project." + ] + }, + "delete": { + "summary": "Remove project access for a user", + "description": "Removes the user from the current project.", + "operationId": "remove-user-project-access", + "tags": [ + "User Access" + ], + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "remove-user-project-access", + "x-tag-id-kebab": "User-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Removes the user from the current project." + ] + } + }, + "/teams/{team_id}/project-access": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamID" + } + ], + "get": { + "summary": "List project access for a team", + "description": "Returns a list of items representing the team's project access.", + "operationId": "list-team-project-access", + "tags": [ + "Team Access" + ], + "parameters": [ + { + "$ref": "#/components/parameters/PageSizeAccess" + }, + { + "$ref": "#/components/parameters/PageBefore" + }, + { + "$ref": "#/components/parameters/PageAfter" + }, + { + "in": "query", + "name": "sort", + "description": "Allows sorting by a single field.
\nUse a dash (\"-\") to sort descending.
\nSupported fields: `project_title`, `granted_at`, `updated_at`.\n", + "schema": { + "type": "string", + "example": "-updated_at" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TeamProjectAccess" + } + }, + "_links": { + "$ref": "#/components/schemas/ListLinks" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "list-team-project-access", + "x-tag-id-kebab": "Team-Access", + "x-return-types-displayReturn": false, + "x-return-types": {}, + "x-phpdoc": {}, + "x-returnable": true, + "x-description": [ + "Returns a list of items representing the team's project access." + ] + }, + "post": { + "summary": "Grant project access to a team", + "description": "Adds the team to one or more specified projects.", + "operationId": "grant-team-project-access", + "tags": [ + "Team Access" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "description": "ID of the project." + } + }, + "required": [ + "project_id" + ] + } + } + } + } + }, + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + }, + "x-property-id-kebab": "grant-team-project-access", + "x-tag-id-kebab": "Team-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Adds the team to one or more specified projects." + ] + } + }, + "/teams/{team_id}/project-access/{project_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamID" + }, + { + "$ref": "#/components/parameters/ProjectID" + } + ], + "get": { + "summary": "Get project access for a team", + "description": "Retrieves the team's permissions for the current project.", + "operationId": "get-team-project-access", + "tags": [ + "Team Access" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TeamProjectAccess" + } + } + } + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "get-team-project-access", + "x-tag-id-kebab": "Team-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\TeamProjectAccess" + ], + "x-return-types-union": "\\Upsun\\Model\\TeamProjectAccess", + "x-phpdoc": { + "return": "\\Upsun\\Model\\TeamProjectAccess" + }, + "x-returnable": true, + "x-description": [ + "Retrieves the team's permissions for the current project." + ] + }, + "delete": { + "summary": "Remove project access for a team", + "description": "Removes the team from the current project.", + "operationId": "remove-team-project-access", + "tags": [ + "Team Access" + ], + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + }, + "x-property-id-kebab": "remove-team-project-access", + "x-tag-id-kebab": "Team-Access", + "x-return-types-displayReturn": false, + "x-return-types": [ + "void" + ], + "x-return-types-union": "void", + "x-phpdoc": {}, + "x-returnable": false, + "x-description": [ + "Removes the team from the current project." + ] + } + }, + "/projects/{projectId}/environments/{environmentId}/deployments/next": { + "patch": { + "summary": "Update the next deployment", + "description": "Update resources for either webapps, services, or workers in the next deployment.", + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "environmentId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "webapps": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "resources": { + "$ref": "#/components/schemas/ResourceConfig" + }, + "instance_count": { + "type": "integer", + "nullable": true, + "description": "Number of instances to run for the webapp", + "example": 2 + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk Size", + "description": "Size of the disk in Bytes for the webapp", + "example": 1024 + } + } + } + }, + "services": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "resources": { + "$ref": "#/components/schemas/ResourceConfig" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk Size", + "description": "Size of the disk in Bytes for the service", + "example": 1024 + } + } + } + }, + "workers": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "resources": { + "$ref": "#/components/schemas/ResourceConfig" + }, + "instance_count": { + "type": "integer", + "nullable": true, + "description": "Number of instances to run for the worker", + "example": 1 + } + } + } + } + } + } + } + } + }, + "responses": { + "default": { + "description": "Deployment successfully updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptedResponse" + } + } + } + } + }, + "tags": [ + "Deployment" + ], + "operationId": "update-projects-environments-deployments-next", + "x-property-id-kebab": "update-projects-environments-deployments-next", + "x-tag-id-kebab": "Deployment", + "x-return-types-displayReturn": false, + "x-return-types": [ + "\\Upsun\\Model\\AcceptedResponse" + ], + "x-return-types-union": "\\Upsun\\Model\\AcceptedResponse", + "x-phpdoc": { + "return": "\\Upsun\\Model\\AcceptedResponse" + }, + "x-returnable": true, + "x-description": [ + "Update resources for either webapps, services, or workers in the next deployment." + ] + } + } + }, + "components": { + "schemas": { + "Alert": { + "description": "The alert object.", + "properties": { + "id": { + "description": "The identification of the alert type.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The identification of the alert type." + ] + }, + "active": { + "description": "Whether the alert is currently active.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Whether the alert is currently active." + ] + }, + "alerts_sent": { + "description": "The amount of alerts of this type that have been sent so far.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The amount of alerts of this type that have been sent so far." + ] + }, + "last_alert_at": { + "description": "The time the last alert has been sent.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The time the last alert has been sent." + ] + }, + "updated_at": { + "description": "The time the alert has last been updated.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The time the alert has last been updated." + ] + }, + "config": { + "description": "The alert type specific configuration.", + "type": "object", + "x-isDateTime": false, + "x-description": [ + "The alert type specific configuration." + ] + } + }, + "type": "object", + "x-description": [ + "The alert object." + ] + }, + "LineItem": { + "description": "A line item in an order.", + "properties": { + "type": { + "description": "The type of line item.", + "type": "string", + "enum": [ + "project_plan", + "project_feature", + "project_subtotal", + "organization_plan", + "organization_feature", + "organization_subtotal" + ], + "x-isDateTime": false, + "x-description": [ + "The type of line item." + ] + }, + "license_id": { + "description": "The associated subscription identifier.", + "type": "number", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The associated subscription identifier." + ] + }, + "project_id": { + "description": "The associated project identifier.", + "type": "string", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The associated project identifier." + ] + }, + "product": { + "description": "Display name of the line item product.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Display name of the line item product." + ] + }, + "sku": { + "description": "The line item product SKU.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The line item product SKU." + ] + }, + "total": { + "description": "Total price as a decimal.", + "type": "number", + "x-isDateTime": false, + "x-description": [ + "Total price as a decimal." + ] + }, + "total_formatted": { + "description": "Total price, formatted with currency.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Total price, formatted with currency." + ] + }, + "components": { + "description": "The price components for the line item, keyed by type.", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/LineItemComponent" + }, + "x-isDateTime": false, + "x-description": [ + "The price components for the line item, keyed by type." + ] + }, + "exclude_from_invoice": { + "description": "Line item should not be considered billable.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Line item should not be considered billable." + ] + } + }, + "type": "object", + "x-description": [ + "A line item in an order." + ] + }, + "LineItemComponent": { + "description": "A price component for a line item.", + "properties": { + "amount": { + "description": "The price as a decimal.", + "type": "number", + "x-isDateTime": false, + "x-description": [ + "The price as a decimal." + ] + }, + "amount_formatted": { + "description": "The price formatted with currency.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The price formatted with currency." + ] + }, + "display_title": { + "description": "The display title for the component.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The display title for the component." + ] + }, + "currency": { + "description": "The currency code for the component.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The currency code for the component." + ] + } + }, + "type": "object", + "x-description": [ + "A price component for a line item." + ] + }, + "Address": { + "description": "The address of the user.", + "properties": { + "country": { + "description": "Two-letter country codes are used to represent countries and states", + "type": "string", + "format": "ISO ALPHA-2", + "x-isDateTime": false, + "x-description": [ + "Two-letter country codes are used to represent countries and states" + ] + }, + "name_line": { + "description": "The full name of the user", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The full name of the user" + ] + }, + "premise": { + "description": "Premise (i.e. Apt, Suite, Bldg.)", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Premise (i.e. Apt, Suite, Bldg.)" + ] + }, + "sub_premise": { + "description": "Sub Premise (i.e. Suite, Apartment, Floor, Unknown.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Sub Premise (i.e. Suite, Apartment, Floor, Unknown." + ] + }, + "thoroughfare": { + "description": "The address of the user", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The address of the user" + ] + }, + "administrative_area": { + "description": "The administrative area of the user address", + "type": "string", + "format": "ISO ALPHA-2", + "x-isDateTime": false, + "x-description": [ + "The administrative area of the user address" + ] + }, + "sub_administrative_area": { + "description": "The sub-administrative area of the user address", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The sub-administrative area of the user address" + ] + }, + "locality": { + "description": "The locality of the user address", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The locality of the user address" + ] + }, + "dependent_locality": { + "description": "The dependant_locality area of the user address", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The dependant_locality area of the user address" + ] + }, + "postal_code": { + "description": "The postal code area of the user address", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The postal code area of the user address" + ] + } + }, + "type": "object", + "x-description": [ + "The address of the user." + ] + }, + "Components": { + "description": "The components of the project", + "properties": { + "voucher/vat/baseprice": { + "description": "stub", + "type": "object", + "x-isDateTime": false, + "x-description": [ + "stub" + ] + } + }, + "type": "object", + "x-description": [ + "The components of the project" + ] + }, + "Discount": { + "description": "The discount object.", + "properties": { + "id": { + "description": "The ID of the organization discount.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The ID of the organization discount." + ] + }, + "organization_id": { + "description": "The ULID of the organization the discount applies to.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The ULID of the organization the discount applies to." + ] + }, + "type": { + "description": "The machine name of the discount type.", + "type": "string", + "enum": [ + "allowance", + "startup", + "enterprise" + ], + "x-isDateTime": false, + "x-description": [ + "The machine name of the discount type." + ] + }, + "type_label": { + "description": "The label of the discount type.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The label of the discount type." + ] + }, + "status": { + "description": "The status of the discount.", + "type": "string", + "enum": [ + "inactive", + "active", + "expired", + "deactivated" + ], + "x-isDateTime": false, + "x-description": [ + "The status of the discount." + ] + }, + "commitment": { + "description": "The minimum commitment associated with the discount (if applicable).", + "properties": { + "months": { + "description": "Commitment period length in months.", + "type": "integer", + "x-description": [ + "Commitment period length in months." + ] + }, + "amount": { + "description": "Commitment amounts.", + "properties": { + "monthly": { + "$ref": "#/components/schemas/CurrencyAmount" + }, + "commitment_period": { + "$ref": "#/components/schemas/CurrencyAmount" + }, + "contract_total": { + "$ref": "#/components/schemas/CurrencyAmount" + } + }, + "type": "object", + "x-description": [ + "Commitment amounts." + ] + }, + "net": { + "description": "Net commitment amounts (discount deducted).", + "properties": { + "monthly": { + "$ref": "#/components/schemas/CurrencyAmount" + }, + "commitment_period": { + "$ref": "#/components/schemas/CurrencyAmount" + }, + "contract_total": { + "$ref": "#/components/schemas/CurrencyAmount" + } + }, + "type": "object", + "x-description": [ + "Net commitment amounts (discount deducted)." + ] + } + }, + "type": "object", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The minimum commitment associated with the discount (if applicable)." + ] + }, + "total_months": { + "description": "The contract length in months (if applicable).", + "type": "integer", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The contract length in months (if applicable)." + ] + }, + "discount": { + "description": "Discount value per relevant time periods.", + "properties": { + "monthly": { + "$ref": "#/components/schemas/CurrencyAmount" + }, + "commitment_period": { + "$ref": "#/components/schemas/CurrencyAmountNullable" + }, + "contract_total": { + "$ref": "#/components/schemas/CurrencyAmountNullable" + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "Discount value per relevant time periods." + ] + }, + "config": { + "description": "The discount type specific configuration.", + "type": "object", + "x-isDateTime": false, + "x-description": [ + "The discount type specific configuration." + ] + }, + "start_at": { + "description": "The start time of the discount period.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The start time of the discount period." + ] + }, + "end_at": { + "description": "The end time of the discount period (if applicable).", + "type": "string", + "format": "date-time", + "nullable": true, + "x-isDateTime": true, + "x-description": [ + "The end time of the discount period (if applicable)." + ] + } + }, + "type": "object", + "x-description": [ + "The discount object." + ] + }, + "CurrencyAmount": { + "description": "Currency amount with detailed components.", + "properties": { + "formatted": { + "description": "Formatted currency value.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Formatted currency value." + ] + }, + "amount": { + "description": "Plain amount.", + "type": "number", + "format": "float", + "x-isDateTime": false, + "x-description": [ + "Plain amount." + ] + }, + "currency_code": { + "description": "Currency code.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Currency code." + ] + }, + "currency_symbol": { + "description": "Currency symbol.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Currency symbol." + ] + } + }, + "type": "object", + "x-description": [ + "Currency amount with detailed components." + ] + }, + "CurrencyAmountNullable": { + "description": "Currency amount with detailed components.", + "properties": { + "formatted": { + "description": "Formatted currency value.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Formatted currency value." + ] + }, + "amount": { + "description": "Plain amount.", + "type": "number", + "format": "float", + "x-isDateTime": false, + "x-description": [ + "Plain amount." + ] + }, + "currency_code": { + "description": "Currency code.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Currency code." + ] + }, + "currency_symbol": { + "description": "Currency symbol.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Currency symbol." + ] + } + }, + "type": "object", + "nullable": true, + "x-description": [ + "Currency amount with detailed components." + ] + }, + "OwnerInfo": { + "description": "Project owner information that can be exposed to collaborators.", + "properties": { + "type": { + "description": "Type of the owner, usually 'user'.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Type of the owner, usually 'user'." + ] + }, + "username": { + "description": "The username of the owner.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The username of the owner." + ] + }, + "display_name": { + "description": "The full name of the owner.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The full name of the owner." + ] + } + }, + "type": "object", + "x-description": [ + "Project owner information that can be exposed to collaborators." + ] + }, + "SshKey": { + "description": "The ssh key object.", + "properties": { + "key_id": { + "description": "The ID of the public key.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The ID of the public key." + ] + }, + "uid": { + "description": "The internal user ID.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The internal user ID." + ] + }, + "fingerprint": { + "description": "The fingerprint of the public key.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The fingerprint of the public key." + ] + }, + "title": { + "description": "The title of the public key.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The title of the public key." + ] + }, + "value": { + "description": "The actual value of the public key.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The actual value of the public key." + ] + }, + "changed": { + "description": "The time of the last key modification (ISO 8601)", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The time of the last key modification (ISO 8601)" + ] + } + }, + "type": "object", + "x-description": [ + "The ssh key object." + ] + }, + "Region": { + "description": "The hosting region.", + "properties": { + "id": { + "description": "The ID of the region.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The ID of the region." + ] + }, + "label": { + "description": "The human-readable name of the region.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The human-readable name of the region." + ] + }, + "zone": { + "description": "Geographical zone of the region", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Geographical zone of the region" + ] + }, + "selection_label": { + "description": "The label to display when choosing between regions for new projects.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The label to display when choosing between regions for new projects." + ] + }, + "project_label": { + "description": "The label to display on existing projects.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The label to display on existing projects." + ] + }, + "timezone": { + "description": "Default timezone of the region", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Default timezone of the region" + ] + }, + "available": { + "description": "Indicator whether or not this region is selectable during the checkout. Not available regions will never show up during checkout.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Indicator whether or not this region is selectable during the checkout. Not available regions will never show up", + "during checkout." + ] + }, + "private": { + "description": "Indicator whether or not this platform is for private use only.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Indicator whether or not this platform is for private use only." + ] + }, + "endpoint": { + "description": "Link to the region API endpoint.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Link to the region API endpoint." + ] + }, + "provider": { + "description": "Information about the region provider.", + "properties": { + "name": { + "type": "string" + }, + "logo": { + "type": "string" + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "Information about the region provider." + ] + }, + "datacenter": { + "description": "Information about the region provider data center.", + "properties": { + "name": { + "type": "string" + }, + "label": { + "type": "string" + }, + "location": { + "type": "string" + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "Information about the region provider data center." + ] + }, + "environmental_impact": { + "description": "Information about the region provider's environmental impact.", + "properties": { + "zone": { + "type": "string" + }, + "carbon_intensity": { + "type": "string" + }, + "green": { + "type": "boolean" + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "Information about the region provider's environmental impact." + ] + } + }, + "type": "object", + "x-description": [ + "The hosting region." + ] + }, + "Subscription": { + "description": "The subscription object.", + "properties": { + "id": { + "description": "The internal ID of the subscription.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The internal ID of the subscription." + ] + }, + "status": { + "description": "The status of the subscription.", + "type": "string", + "enum": [ + "requested", + "provisioning failure", + "provisioning", + "active", + "suspended", + "deleted" + ], + "x-isDateTime": false, + "x-description": [ + "The status of the subscription." + ] + }, + "created_at": { + "description": "The date and time when the subscription was created.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The date and time when the subscription was created." + ] + }, + "updated_at": { + "description": "The date and time when the subscription was last updated.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The date and time when the subscription was last updated." + ] + }, + "owner": { + "description": "The UUID of the owner.", + "type": "string", + "format": "uuid", + "x-isDateTime": false, + "x-description": [ + "The UUID of the owner." + ] + }, + "owner_info": { + "$ref": "#/components/schemas/OwnerInfo" + }, + "vendor": { + "description": "The machine name of the vendor the subscription belongs to.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The machine name of the vendor the subscription belongs to." + ] + }, + "plan": { + "description": "The plan type of the subscription.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The plan type of the subscription." + ] + }, + "environments": { + "description": "The number of environments which can be provisioned on the project.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The number of environments which can be provisioned on the project." + ] + }, + "storage": { + "description": "The total storage available to each environment, in MiB. Only multiples of 1024 are accepted as legal values.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The total storage available to each environment, in MiB. Only multiples of 1024 are accepted as legal values." + ] + }, + "user_licenses": { + "description": "The number of chargeable users who currently have access to the project. Manage this value by adding and removing users through the Platform project API. Staff and billing/administrative contacts can be added to a project for no charge. Contact support for questions about user licenses.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The number of chargeable users who currently have access to the project. Manage this value by adding and removing", + "users through the Platform project API. Staff and billing/administrative contacts can be added to a project for", + "no charge. Contact support for questions about user licenses." + ] + }, + "project_id": { + "description": "The unique ID string of the project.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The unique ID string of the project." + ] + }, + "project_endpoint": { + "description": "The project API endpoint for the project.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The project API endpoint for the project." + ] + }, + "project_title": { + "description": "The name given to the project. Appears as the title in the UI.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The name given to the project. Appears as the title in the UI." + ] + }, + "project_region": { + "description": "The machine name of the region where the project is located. Cannot be changed after project creation.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The machine name of the region where the project is located. Cannot be changed after project creation." + ] + }, + "project_region_label": { + "description": "The human-readable name of the region where the project is located.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The human-readable name of the region where the project is located." + ] + }, + "project_ui": { + "description": "The URL for the project's user interface.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The URL for the project's user interface." + ] + }, + "project_options": { + "$ref": "#/components/schemas/ProjectOptions" + }, + "agency_site": { + "description": "True if the project is an agency site.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "True if the project is an agency site." + ] + }, + "invoiced": { + "description": "Whether the subscription is invoiced.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Whether the subscription is invoiced." + ] + }, + "hipaa": { + "description": "Whether the project is marked as HIPAA.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Whether the project is marked as HIPAA." + ] + }, + "is_trial_plan": { + "description": "Whether the project is currently on a trial plan.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Whether the project is currently on a trial plan." + ] + }, + "services": { + "description": "Details of the attached services.", + "type": "array", + "items": { + "description": "Details of a service", + "type": "object" + }, + "x-isDateTime": false, + "x-description": [ + "Details of the attached services." + ] + }, + "green": { + "description": "Whether the subscription is considered green (on a green region, belonging to a green vendor) for billing purposes.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Whether the subscription is considered green (on a green region, belonging to a green vendor) for billing", + "purposes." + ] + } + }, + "type": "object", + "x-description": [ + "The subscription object." + ] + }, + "ProjectOptions": { + "description": "The project options object.", + "properties": { + "defaults": { + "description": "The initial values applied to the project.", + "properties": { + "settings": { + "description": "The project settings.", + "type": "object", + "x-description": [ + "The project settings." + ] + }, + "variables": { + "description": "The project variables.", + "type": "object", + "x-description": [ + "The project variables." + ] + }, + "access": { + "description": "The project access list.", + "type": "object", + "x-description": [ + "The project access list." + ] + }, + "capabilities": { + "description": "The project capabilities.", + "type": "object", + "x-description": [ + "The project capabilities." + ] + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "The initial values applied to the project." + ] + }, + "enforced": { + "description": "The enforced values applied to the project.", + "properties": { + "settings": { + "description": "The project settings.", + "type": "object", + "x-description": [ + "The project settings." + ] + }, + "capabilities": { + "description": "The project capabilities.", + "type": "object", + "x-description": [ + "The project capabilities." + ] + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "The enforced values applied to the project." + ] + }, + "regions": { + "description": "The available regions.", + "type": "array", + "items": { + "type": "string" + }, + "x-isDateTime": false, + "x-description": [ + "The available regions." + ] + }, + "plans": { + "description": "The available plans.", + "type": "array", + "items": { + "type": "string" + }, + "x-isDateTime": false, + "x-description": [ + "The available plans." + ] + }, + "billing": { + "description": "The billing settings.", + "type": "object", + "x-isDateTime": false, + "x-description": [ + "The billing settings." + ] + } + }, + "type": "object", + "x-description": [ + "The project options object." + ] + }, + "SubscriptionCurrentUsageObject": { + "description": "A subscription's usage group current usage object.", + "properties": { + "cpu_app": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "storage_app_services": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "memory_app": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "cpu_services": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "memory_services": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "backup_storage": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "build_cpu": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "build_memory": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "egress_bandwidth": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "ingress_requests": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "logs_fwd_content_size": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "fastly_bandwidth": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + }, + "fastly_requests": { + "$ref": "#/components/schemas/UsageGroupCurrentUsageProperties" + } + }, + "type": "object", + "x-description": [ + "A subscription's usage group current usage object." + ] + }, + "UsageGroupCurrentUsageProperties": { + "description": "Current usage info for a usage group.", + "properties": { + "title": { + "description": "The title of the usage group.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The title of the usage group." + ] + }, + "type": { + "description": "The usage group type.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "The usage group type." + ] + }, + "current_usage": { + "description": "The value of current usage for the group.", + "type": "number", + "x-isDateTime": false, + "x-description": [ + "The value of current usage for the group." + ] + }, + "current_usage_formatted": { + "description": "The formatted value of current usage for the group.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The formatted value of current usage for the group." + ] + }, + "not_charged": { + "description": "Whether the group is not charged for the subscription.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Whether the group is not charged for the subscription." + ] + }, + "free_quantity": { + "description": "The amount of free usage for the group.", + "type": "number", + "x-isDateTime": false, + "x-description": [ + "The amount of free usage for the group." + ] + }, + "free_quantity_formatted": { + "description": "The formatted amount of free usage for the group.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The formatted amount of free usage for the group." + ] + }, + "daily_average": { + "description": "The daily average usage calculated for the group.", + "type": "number", + "x-isDateTime": false, + "x-description": [ + "The daily average usage calculated for the group." + ] + }, + "daily_average_formatted": { + "description": "The formatted daily average usage calculated for the group.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The formatted daily average usage calculated for the group." + ] + } + }, + "type": "object", + "x-description": [ + "Current usage info for a usage group." + ] + }, + "HalLinks": { + "description": "Links to _self, and previous or next page, given that they exist.", + "properties": { + "self": { + "description": "The cardinal link to the self resource.", + "properties": { + "title": { + "description": "Title of the link", + "type": "string", + "x-description": [ + "Title of the link" + ] + }, + "href": { + "description": "URL of the link", + "type": "string", + "x-description": [ + "URL of the link" + ] + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "The cardinal link to the self resource." + ] + }, + "previous": { + "description": "The link to the previous resource page, given that it exists.", + "properties": { + "title": { + "description": "Title of the link", + "type": "string", + "x-description": [ + "Title of the link" + ] + }, + "href": { + "description": "URL of the link", + "type": "string", + "x-description": [ + "URL of the link" + ] + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "The link to the previous resource page, given that it exists." + ] + }, + "next": { + "description": "The link to the next resource page, given that it exists.", + "properties": { + "title": { + "description": "Title of the link", + "type": "string", + "x-description": [ + "Title of the link" + ] + }, + "href": { + "description": "URL of the link", + "type": "string", + "x-description": [ + "URL of the link" + ] + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "The link to the next resource page, given that it exists." + ] + } + }, + "type": "object", + "x-description": [ + "Links to _self, and previous or next page, given that they exist." + ] + }, + "Profile": { + "description": "The user profile.", + "properties": { + "id": { + "description": "The user's unique ID.", + "type": "string", + "format": "uuid", + "x-isDateTime": false, + "x-description": [ + "The user's unique ID." + ] + }, + "display_name": { + "description": "The user's display name.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The user's display name." + ] + }, + "email": { + "description": "The user's email address.", + "type": "string", + "format": "email", + "x-isDateTime": false, + "x-description": [ + "The user's email address." + ] + }, + "username": { + "description": "The user's username.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The user's username." + ] + }, + "type": { + "description": "The user's type (user/organization).", + "type": "string", + "enum": [ + "user", + "organization" + ], + "x-isDateTime": false, + "x-description": [ + "The user's type (user/organization)." + ] + }, + "picture": { + "description": "The URL of the user's picture.", + "type": "string", + "format": "url", + "x-isDateTime": false, + "x-description": [ + "The URL of the user's picture." + ] + }, + "company_type": { + "description": "The company type.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The company type." + ] + }, + "company_name": { + "description": "The name of the company.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The name of the company." + ] + }, + "currency": { + "description": "A 3-letter ISO 4217 currency code (assigned according to the billing address).", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "A 3-letter ISO 4217 currency code (assigned according to the billing address)." + ] + }, + "vat_number": { + "description": "The vat number of the user.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The vat number of the user." + ] + }, + "company_role": { + "description": "The role of the user in the company.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The role of the user in the company." + ] + }, + "website_url": { + "description": "The user or company website.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The user or company website." + ] + }, + "new_ui": { + "description": "Whether the new UI features are enabled for this user.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Whether the new UI features are enabled for this user." + ] + }, + "ui_colorscheme": { + "description": "The user's chosen color scheme for user interfaces.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The user's chosen color scheme for user interfaces." + ] + }, + "default_catalog": { + "description": "The URL of a catalog file which overrides the default.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The URL of a catalog file which overrides the default." + ] + }, + "project_options_url": { + "description": "The URL of an account-wide project options file.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The URL of an account-wide project options file." + ] + }, + "marketing": { + "description": "Flag if the user agreed to receive marketing communication.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Flag if the user agreed to receive marketing communication." + ] + }, + "created_at": { + "description": "The timestamp representing when the user account was created.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The timestamp representing when the user account was created." + ] + }, + "updated_at": { + "description": "The timestamp representing when the user account was last modified.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The timestamp representing when the user account was last modified." + ] + }, + "billing_contact": { + "description": "The e-mail address of a contact to whom billing notices will be sent.", + "type": "string", + "format": "email", + "x-isDateTime": false, + "x-description": [ + "The e-mail address of a contact to whom billing notices will be sent." + ] + }, + "invoiced": { + "description": "The customer is invoiced.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "The customer is invoiced." + ] + }, + "customer_type": { + "description": "The customer type.", + "type": "string", + "enum": [ + "individual", + "corporation", + "government" + ], + "x-isDateTime": false, + "x-description": [ + "The customer type." + ] + } + }, + "type": "object", + "x-description": [ + "The user profile." + ] + }, + "AddressMetadata": { + "description": "Information about fields required to express an address.", + "properties": { + "metadata": { + "description": "Address field metadata.", + "properties": { + "required_fields": { + "description": "Fields required to express the address.", + "type": "array", + "items": { + "type": "string" + }, + "x-description": [ + "Fields required to express the address." + ] + }, + "field_labels": { + "description": "Localized labels for address fields.", + "type": "object", + "x-description": [ + "Localized labels for address fields." + ] + }, + "show_vat": { + "description": "Whether this country supports a VAT number.", + "type": "boolean", + "x-description": [ + "Whether this country supports a VAT number." + ] + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "Address field metadata." + ] + } + }, + "type": "object", + "x-description": [ + "Information about fields required to express an address." + ] + }, + "Ticket": { + "description": "The support ticket object.", + "properties": { + "ticket_id": { + "description": "The ID of the ticket.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The ID of the ticket." + ] + }, + "created": { + "description": "The time when the support ticket was created.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The time when the support ticket was created." + ] + }, + "updated": { + "description": "The time when the support ticket was updated.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The time when the support ticket was updated." + ] + }, + "type": { + "description": "A type of the ticket.", + "type": "string", + "enum": [ + "problem", + "task", + "incident", + "question" + ], + "x-isDateTime": false, + "x-description": [ + "A type of the ticket." + ] + }, + "subject": { + "description": "A title of the ticket.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "A title of the ticket." + ] + }, + "description": { + "description": "The description body of the support ticket.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The description body of the support ticket." + ] + }, + "priority": { + "description": "A priority of the ticket.", + "type": "string", + "enum": [ + "low", + "normal", + "high", + "urgent" + ], + "x-isDateTime": false, + "x-description": [ + "A priority of the ticket." + ] + }, + "followup_tid": { + "description": "Followup ticket ID. The unique ID of the ticket which this ticket is a follow-up to.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Followup ticket ID. The unique ID of the ticket which this ticket is a follow-up to." + ] + }, + "status": { + "description": "The status of the support ticket.", + "type": "string", + "enum": [ + "closed", + "deleted", + "hold", + "new", + "open", + "pending", + "solved" + ], + "x-isDateTime": false, + "x-description": [ + "The status of the support ticket." + ] + }, + "recipient": { + "description": "Email address of the ticket recipient, defaults to support@upsun.com.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Email address of the ticket recipient, defaults to support@upsun.com." + ] + }, + "requester_id": { + "description": "UUID of the ticket requester.", + "type": "string", + "format": "uuid", + "x-isDateTime": false, + "x-description": [ + "UUID of the ticket requester." + ] + }, + "submitter_id": { + "description": "UUID of the ticket submitter.", + "type": "string", + "format": "uuid", + "x-isDateTime": false, + "x-description": [ + "UUID of the ticket submitter." + ] + }, + "assignee_id": { + "description": "UUID of the ticket assignee.", + "type": "string", + "format": "uuid", + "x-isDateTime": false, + "x-description": [ + "UUID of the ticket assignee." + ] + }, + "organization_id": { + "description": "A reference id that is usable to find the commerce license.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "A reference id that is usable to find the commerce license." + ] + }, + "collaborator_ids": { + "description": "A list of the collaborators uuids for this ticket.", + "type": "array", + "items": { + "type": "string" + }, + "x-isDateTime": false, + "x-description": [ + "A list of the collaborators uuids for this ticket." + ] + }, + "has_incidents": { + "description": "Whether or not this ticket has incidents.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "Whether or not this ticket has incidents." + ] + }, + "due": { + "description": "A time that the ticket is due at.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "A time that the ticket is due at." + ] + }, + "tags": { + "description": "A list of tags assigned to the ticket.", + "type": "array", + "items": { + "type": "string" + }, + "x-isDateTime": false, + "x-description": [ + "A list of tags assigned to the ticket." + ] + }, + "subscription_id": { + "description": "The internal ID of the subscription.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The internal ID of the subscription." + ] + }, + "ticket_group": { + "description": "Maps to zendesk field 'Request group'.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Maps to zendesk field 'Request group'." + ] + }, + "support_plan": { + "description": "Maps to zendesk field 'The support plan associated with this ticket.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Maps to zendesk field 'The support plan associated with this ticket." + ] + }, + "affected_url": { + "description": "The affected URL associated with the support ticket.", + "type": "string", + "format": "url", + "x-isDateTime": false, + "x-description": [ + "The affected URL associated with the support ticket." + ] + }, + "queue": { + "description": "The queue the support ticket is in.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The queue the support ticket is in." + ] + }, + "issue_type": { + "description": "The issue type of the support ticket.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The issue type of the support ticket." + ] + }, + "resolution_time": { + "description": "Maps to zendesk field 'Resolution Time'.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "Maps to zendesk field 'Resolution Time'." + ] + }, + "response_time": { + "description": "Maps to zendesk field 'Response Time (time from request to reply).", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "Maps to zendesk field 'Response Time (time from request to reply)." + ] + }, + "project_url": { + "description": "Maps to zendesk field 'Project URL'.", + "type": "string", + "format": "url", + "x-isDateTime": false, + "x-description": [ + "Maps to zendesk field 'Project URL'." + ] + }, + "region": { + "description": "Maps to zendesk field 'Region'.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Maps to zendesk field 'Region'." + ] + }, + "category": { + "description": "Maps to zendesk field 'Category'.", + "type": "string", + "enum": [ + "access", + "billing_question", + "complaint", + "compliance_question", + "configuration_change", + "general_question", + "incident_outage", + "bug_report", + "onboarding", + "report_a_gui_bug", + "close_my_account" + ], + "x-isDateTime": false, + "x-description": [ + "Maps to zendesk field 'Category'." + ] + }, + "environment": { + "description": "Maps to zendesk field 'Environment'.", + "type": "string", + "enum": [ + "env_development", + "env_staging", + "env_production" + ], + "x-isDateTime": false, + "x-description": [ + "Maps to zendesk field 'Environment'." + ] + }, + "ticket_sharing_status": { + "description": "Maps to zendesk field 'Ticket Sharing Status'.", + "type": "string", + "enum": [ + "ts_sent_to_platform", + "ts_accepted_by_platform", + "ts_returned_from_platform", + "ts_solved_by_platform", + "ts_rejected_by_platform" + ], + "x-isDateTime": false, + "x-description": [ + "Maps to zendesk field 'Ticket Sharing Status'." + ] + }, + "application_ticket_url": { + "description": "Maps to zendesk field 'Application Ticket URL'.", + "type": "string", + "format": "url", + "x-isDateTime": false, + "x-description": [ + "Maps to zendesk field 'Application Ticket URL'." + ] + }, + "infrastructure_ticket_url": { + "description": "Maps to zendesk field 'Infrastructure Ticket URL'.", + "type": "string", + "format": "url", + "x-isDateTime": false, + "x-description": [ + "Maps to zendesk field 'Infrastructure Ticket URL'." + ] + }, + "jira": { + "description": "A list of JIRA issues related to the support ticket.", + "type": "array", + "items": { + "properties": { + "id": { + "description": "The id of the query.", + "type": "integer" + }, + "ticket_id": { + "description": "The id of the ticket.", + "type": "integer" + }, + "issue_id": { + "description": "The issue id number.", + "type": "integer" + }, + "issue_key": { + "description": "The issue key.", + "type": "string" + }, + "created_at": { + "description": "The created at timestamp.", + "type": "number", + "format": "float" + }, + "updated_at": { + "description": "The updated at timestamp.", + "type": "number", + "format": "float" + } + }, + "type": "object" + }, + "x-isDateTime": false, + "x-description": [ + "A list of JIRA issues related to the support ticket." + ] + }, + "zd_ticket_url": { + "description": "URL to the customer-facing ticket in Zendesk.", + "type": "string", + "format": "url", + "x-isDateTime": false, + "x-description": [ + "URL to the customer-facing ticket in Zendesk." + ] + } + }, + "type": "object", + "x-description": [ + "The support ticket object." + ] + }, + "CurrentUser": { + "description": "The user object.", + "properties": { + "id": { + "description": "The UUID of the owner.", + "type": "string", + "format": "uuid", + "x-isDateTime": false, + "x-description": [ + "The UUID of the owner." + ] + }, + "uuid": { + "description": "The UUID of the owner.", + "type": "string", + "format": "uuid", + "x-isDateTime": false, + "x-description": [ + "The UUID of the owner." + ] + }, + "username": { + "description": "The username of the owner.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The username of the owner." + ] + }, + "display_name": { + "description": "The full name of the owner.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The full name of the owner." + ] + }, + "status": { + "description": "Status of the user. 0 = blocked; 1 = active.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "Status of the user. 0 = blocked; 1 = active." + ] + }, + "mail": { + "description": "The email address of the owner.", + "type": "string", + "format": "email", + "x-isDateTime": false, + "x-description": [ + "The email address of the owner." + ] + }, + "ssh_keys": { + "description": "The list of user's public SSH keys.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SshKey" + }, + "x-isDateTime": false, + "x-description": [ + "The list of user's public SSH keys." + ] + }, + "has_key": { + "description": "The indicator whether the user has a public ssh key on file or not.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "The indicator whether the user has a public ssh key on file or not." + ] + }, + "projects": { + "type": "array", + "items": { + "properties": { + "id": { + "description": "The unique ID string of the project.", + "type": "string" + }, + "name": { + "description": "The name given to the project. Appears as the title in the user interface.", + "type": "string" + }, + "title": { + "description": "The name given to the project. Appears as the title in the user interface.", + "type": "string" + }, + "cluster": { + "description": "The machine name of the region where the project is located. Cannot be changed after project creation.", + "type": "string" + }, + "cluster_label": { + "description": "The human-readable name of the region where the project is located.", + "type": "string" + }, + "region": { + "description": "The machine name of the region where the project is located. Cannot be changed after project creation.", + "type": "string" + }, + "region_label": { + "description": "The human-readable name of the region where the project is located.", + "type": "string" + }, + "uri": { + "description": "The URL for the project's user interface.", + "type": "string" + }, + "endpoint": { + "description": "The project API endpoint for the project.", + "type": "string" + }, + "license_id": { + "description": "The ID of the subscription.", + "type": "integer" + }, + "owner": { + "description": "The UUID of the owner.", + "type": "string", + "format": "uuid" + }, + "owner_info": { + "$ref": "#/components/schemas/OwnerInfo" + }, + "plan": { + "description": "The plan type of the subscription.", + "type": "string" + }, + "subscription_id": { + "description": "The ID of the subscription.", + "type": "integer" + }, + "status": { + "description": "The status of the project.", + "type": "string" + }, + "vendor": { + "description": "The machine name of the vendor the subscription belongs to.", + "type": "string" + }, + "vendor_label": { + "description": "The machine name of the vendor the subscription belongs to.", + "type": "string" + }, + "vendor_website": { + "description": "The URL of the vendor the subscription belongs to.", + "type": "string", + "format": "url" + }, + "vendor_resources": { + "description": "The link to the resources of the vendor the subscription belongs to.", + "type": "string" + }, + "created_at": { + "description": "The creation date of the subscription.", + "type": "string", + "format": "date-time" + } + }, + "type": "object" + }, + "x-isDateTime": false + }, + "sequence": { + "description": "The sequential ID of the user.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The sequential ID of the user." + ] + }, + "roles": { + "type": "array", + "items": { + "description": "The user role name.", + "type": "string" + }, + "x-isDateTime": false + }, + "picture": { + "description": "The URL of the user image.", + "type": "string", + "format": "url", + "x-isDateTime": false, + "x-description": [ + "The URL of the user image." + ] + }, + "tickets": { + "description": "Number of support tickets by status.", + "type": "object", + "x-isDateTime": false, + "x-description": [ + "Number of support tickets by status." + ] + } + }, + "type": "object", + "x-description": [ + "The user object." + ] + }, + "Error": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Error message", + "x-isDateTime": false, + "x-description": [ + "Error message" + ] + } + }, + "required": [ + "error" + ] + }, + "OrganizationInvitation": { + "title": "OrganizationInvitation", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of the invitation.", + "x-isDateTime": false, + "x-description": [ + "The ID of the invitation." + ] + }, + "state": { + "type": "string", + "enum": [ + "pending", + "processing", + "accepted", + "cancelled", + "error" + ], + "description": "The invitation state.", + "x-isDateTime": false, + "x-description": [ + "The invitation state." + ] + }, + "organization_id": { + "type": "string", + "description": "The ID of the organization.", + "x-isDateTime": false, + "x-description": [ + "The ID of the organization." + ] + }, + "email": { + "type": "string", + "format": "email", + "description": "The email address of the invitee.", + "x-isDateTime": false, + "x-description": [ + "The email address of the invitee." + ] + }, + "owner": { + "type": "object", + "description": "The inviter.", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of the user.", + "x-description": [ + "The ID of the user." + ] + }, + "display_name": { + "type": "string", + "description": "The user's display name.", + "x-description": [ + "The user's display name." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "The inviter." + ] + }, + "created_at": { + "type": "string", + "description": "The date and time when the invitation was created.", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The date and time when the invitation was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the invitation was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the invitation was last updated." + ] + }, + "finished_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the invitation was finished.", + "nullable": true, + "x-isDateTime": true, + "x-description": [ + "The date and time when the invitation was finished." + ] + }, + "permissions": { + "$ref": "#/components/schemas/OrganizationPermissions" + } + }, + "x-examples": { + "example-1": { + "id": "97f46eca-6276-4993-bfeb-bbb53cba6f08", + "state": "pending", + "organization_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "email": "bob@example.com", + "owner": { + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "display_name": "Alice" + }, + "created_at": "2019-08-24T14:15:22Z", + "updated_at": "2019-08-24T14:15:22Z", + "finished_at": null, + "permissions": [ + "members" + ] + } + } + }, + "OrganizationPermissions": { + "type": "array", + "description": "The permissions the invitee should be given on the organization.", + "items": { + "type": "string", + "enum": [ + "admin", + "billing", + "plans", + "members", + "project:create", + "projects:list" + ] + }, + "x-description": [ + "The permissions the invitee should be given on the organization." + ] + }, + "ProjectInvitation": { + "title": "", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of the invitation.", + "x-isDateTime": false, + "x-description": [ + "The ID of the invitation." + ] + }, + "state": { + "type": "string", + "enum": [ + "pending", + "processing", + "accepted", + "cancelled", + "error" + ], + "description": "The invitation state.", + "x-isDateTime": false, + "x-description": [ + "The invitation state." + ] + }, + "project_id": { + "type": "string", + "description": "The ID of the project.", + "x-isDateTime": false, + "x-description": [ + "The ID of the project." + ] + }, + "role": { + "type": "string", + "enum": [ + "admin", + "viewer" + ], + "description": "The project role.", + "x-isDateTime": false, + "x-description": [ + "The project role." + ] + }, + "email": { + "type": "string", + "format": "email", + "description": "The email address of the invitee.", + "x-isDateTime": false, + "x-description": [ + "The email address of the invitee." + ] + }, + "owner": { + "type": "object", + "description": "The inviter.", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of the user.", + "x-description": [ + "The ID of the user." + ] + }, + "display_name": { + "type": "string", + "description": "The user's display name.", + "x-description": [ + "The user's display name." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "The inviter." + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the invitation was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the invitation was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the invitation was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the invitation was last updated." + ] + }, + "finished_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "The date and time when the invitation was finished.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the invitation was finished." + ] + }, + "environments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The ID of the environment." + }, + "type": { + "type": "string", + "description": "The environment type." + }, + "role": { + "type": "string", + "enum": [ + "admin", + "viewer", + "contributor" + ], + "description": "The environment role." + }, + "title": { + "type": "string", + "description": "The environment title." + } + } + }, + "x-isDateTime": false + } + }, + "x-examples": { + "example-1": { + "id": "97f46eca-6276-4993-bfeb-bbb53cba6f08", + "state": "pending", + "project_id": "652soceglkw4u", + "role": "admin", + "email": "bob@example.com", + "owner": { + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "display_name": "Alice" + }, + "created_at": "2019-08-24T14:15:22Z", + "updated_at": "2019-08-24T14:15:22Z", + "finished_at": null, + "environments": {} + } + } + }, + "User": { + "description": "", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of the user.", + "x-isDateTime": false, + "x-description": [ + "The ID of the user." + ] + }, + "deactivated": { + "type": "boolean", + "description": "Whether the user has been deactivated.", + "x-isDateTime": false, + "x-description": [ + "Whether the user has been deactivated." + ] + }, + "namespace": { + "type": "string", + "description": "The namespace in which the user's username is unique.", + "x-isDateTime": false, + "x-description": [ + "The namespace in which the user's username is unique." + ] + }, + "username": { + "type": "string", + "description": "The user's username.", + "x-isDateTime": false, + "x-description": [ + "The user's username." + ] + }, + "email": { + "type": "string", + "format": "email", + "description": "The user's email address.", + "x-isDateTime": false, + "x-description": [ + "The user's email address." + ] + }, + "email_verified": { + "type": "boolean", + "description": "Whether the user's email address has been verified.", + "x-isDateTime": false, + "x-description": [ + "Whether the user's email address has been verified." + ] + }, + "first_name": { + "type": "string", + "description": "The user's first name.", + "x-isDateTime": false, + "x-description": [ + "The user's first name." + ] + }, + "last_name": { + "type": "string", + "description": "The user's last name.", + "x-isDateTime": false, + "x-description": [ + "The user's last name." + ] + }, + "picture": { + "type": "string", + "format": "uri", + "description": "The user's picture.", + "x-isDateTime": false, + "x-description": [ + "The user's picture." + ] + }, + "company": { + "type": "string", + "description": "The user's company.", + "x-isDateTime": false, + "x-description": [ + "The user's company." + ] + }, + "website": { + "type": "string", + "format": "uri", + "description": "The user's website.", + "x-isDateTime": false, + "x-description": [ + "The user's website." + ] + }, + "country": { + "type": "string", + "maxLength": 2, + "minLength": 2, + "description": "The user's ISO 3166-1 alpha-2 country code.", + "x-isDateTime": false, + "x-description": [ + "The user's ISO 3166-1 alpha-2 country code." + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the user was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the user was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the user was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the user was last updated." + ] + }, + "consented_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the user consented to the Terms of Service.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the user consented to the Terms of Service." + ] + }, + "consent_method": { + "type": "string", + "description": "The method by which the user consented to the Terms of Service.", + "enum": [ + "opt-in", + "text-ref" + ], + "x-isDateTime": false, + "x-description": [ + "The method by which the user consented to the Terms of Service." + ] + } + }, + "required": [ + "id", + "deactivated", + "namespace", + "username", + "email", + "email_verified", + "first_name", + "last_name", + "picture", + "company", + "website", + "country", + "created_at", + "updated_at" + ], + "x-examples": { + "example-1": { + "company": "Platform.sh SAS", + "country": "FR", + "created_at": "2010-04-19T10:00:00Z", + "deactivated": false, + "email": "hello@platform.sh", + "email_verified": true, + "first_name": "Hello", + "id": "d81c8ee2-44b3-429f-b944-a33ad7437690", + "last_name": "World", + "namespace": "platformsh", + "picture": "https://accounts.platform.sh/profiles/blimp_profile/themes/platformsh_theme/images/mail/logo.png", + "updated_at": "2021-01-27T13:58:38.06968Z", + "username": "platform-sh", + "website": "https://platform.sh", + "consented_at": "2010-04-19T10:00:00Z", + "consent_method": "opt-in" + } + } + }, + "ListLinks": { + "type": "object", + "properties": { + "self": { + "$ref": "#/components/schemas/Link" + }, + "previous": { + "$ref": "#/components/schemas/Link" + }, + "next": { + "$ref": "#/components/schemas/Link" + } + } + }, + "Link": { + "type": "object", + "title": "Link", + "description": "A hypermedia link to the {current, next, previous} set of items.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link", + "x-isDateTime": false, + "x-description": [ + "URL of the link" + ] + } + }, + "x-description": [ + "A hypermedia link to the {current, next, previous} set of items." + ] + }, + "ApiToken": { + "description": "", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of the token.", + "x-isDateTime": false, + "x-description": [ + "The ID of the token." + ] + }, + "name": { + "type": "string", + "description": "The token name.", + "x-isDateTime": false, + "x-description": [ + "The token name." + ] + }, + "mfa_on_creation": { + "type": "boolean", + "description": "Whether the user had multi-factor authentication (MFA) enabled when they created the token.", + "x-isDateTime": false, + "x-description": [ + "Whether the user had multi-factor authentication (MFA) enabled when they created the token." + ] + }, + "token": { + "type": "string", + "description": "The token in plain text (available only when created).", + "x-isDateTime": false, + "x-description": [ + "The token in plain text (available only when created)." + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the token was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the token was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the token was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the token was last updated." + ] + }, + "last_used_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "description": "The date and time when the token was last exchanged for an access token. This will be null for a token which has never been used, or not used since this API property was added. Note: After an API token is used, the derived access token may continue to be used until its expiry. This also applies to SSH certificate(s) derived from the access token.\n", + "x-isDateTime": true, + "x-description": [ + "The date and time when the token was last exchanged for an access token. This will be null for a", + "token which has never been used, or not used since this API property was added. Note: After an", + "API token is used, the derived access token may continue to be used until its expiry. This also applies to SSH", + "certificate(s) derived from the access token." + ] + } + }, + "x-examples": { + "example-1": { + "created_at": "2019-01-29T08:17:47Z", + "id": "660aa36d-23cf-402b-8889-63af71967f2b", + "name": "Token for CI", + "updated_at": "2019-01-29T08:17:47Z" + } + } + }, + "Connection": { + "description": "", + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "The name of the federation provider.", + "x-isDateTime": false, + "x-description": [ + "The name of the federation provider." + ] + }, + "provider_type": { + "type": "string", + "description": "The type of the federation provider.", + "x-isDateTime": false, + "x-description": [ + "The type of the federation provider." + ] + }, + "is_mandatory": { + "type": "boolean", + "description": "Whether the federated login connection is mandatory.", + "x-isDateTime": false, + "x-description": [ + "Whether the federated login connection is mandatory." + ] + }, + "subject": { + "type": "string", + "description": "The identity on the federation provider.", + "x-isDateTime": false, + "x-description": [ + "The identity on the federation provider." + ] + }, + "email_address": { + "type": "string", + "description": "The email address presented on the federated login connection.", + "x-isDateTime": false, + "x-description": [ + "The email address presented on the federated login connection." + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the connection was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the connection was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the connection was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the connection was last updated." + ] + } + }, + "x-examples": { + "example-1": { + "created_at": "2021-05-24T07:20:35.683264Z", + "provider": "acme-inc-oidc", + "provider_type": "okta", + "subject": "1621840835647277693", + "email_address": "name@example.com", + "updated_at": "2021-05-24T07:20:35.683264Z" + } + } + }, + "OrganizationMfaEnforcement": { + "description": "The MFA enforcement for the organization.", + "type": "object", + "properties": { + "enforce_mfa": { + "type": "boolean", + "description": "Whether the MFA enforcement is enabled.", + "x-isDateTime": false, + "x-description": [ + "Whether the MFA enforcement is enabled." + ] + } + }, + "x-examples": { + "example-1": { + "enforce_mfa": true + } + }, + "x-description": [ + "The MFA enforcement for the organization." + ] + }, + "OrganizationSSOConfig": { + "description": "The SSO configuration for the organization.", + "type": "object", + "allOf": [ + { + "oneOf": [ + { + "$ref": "#/components/schemas/GoogleSSOConfig" + } + ] + }, + { + "type": "object", + "properties": { + "organization_id": { + "type": "string", + "description": "Organization ID.", + "x-description": [ + "Organization ID." + ] + }, + "enforced": { + "type": "boolean", + "description": "Whether the configuration is enforced for all the organization members.", + "x-description": [ + "Whether the configuration is enforced for all the organization members." + ] + }, + "created_at": { + "type": "string", + "description": "The date and time when the SSO configuration was created.", + "format": "date-time", + "x-description": [ + "The date and time when the SSO configuration was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the SSO configuration was last updated.", + "x-description": [ + "The date and time when the SSO configuration was last updated." + ] + } + } + } + ], + "x-examples": { + "example-1": { + "organization_id": "01EY8BWRSQ56EY1TDC32PARAJS", + "provider_type": "google", + "domain": "example.com", + "enforced": true, + "created_at": "2021-05-24T07:20:35.683264Z", + "updated_at": "2021-05-24T07:20:35.683264Z" + } + }, + "x-description": [ + "The SSO configuration for the organization." + ] + }, + "GoogleSSOConfig": { + "type": "object", + "title": "GoogleSSO", + "properties": { + "provider_type": { + "type": "string", + "description": "SSO provider type.", + "enum": [ + "google" + ], + "x-isDateTime": false, + "x-description": [ + "SSO provider type." + ] + }, + "domain": { + "type": "string", + "description": "Google hosted domain.", + "x-isDateTime": false, + "x-description": [ + "Google hosted domain." + ] + } + } + }, + "Team": { + "description": "", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "ulid", + "description": "The ID of the team.", + "x-isDateTime": false, + "x-description": [ + "The ID of the team." + ] + }, + "organization_id": { + "type": "string", + "format": "ulid", + "description": "The ID of the parent organization.", + "x-isDateTime": false, + "x-description": [ + "The ID of the parent organization." + ] + }, + "label": { + "type": "string", + "description": "The human-readable label of the team.", + "x-isDateTime": false, + "x-description": [ + "The human-readable label of the team." + ] + }, + "project_permissions": { + "type": "array", + "description": "Project permissions that are granted to the team.", + "items": { + "type": "string", + "enum": [ + "admin", + "viewer", + "development:admin", + "development:contributor", + "development:viewer", + "staging:admin", + "staging:contributor", + "staging:viewer", + "production:admin", + "production:contributor", + "production:viewer" + ] + }, + "x-isDateTime": false, + "x-description": [ + "Project permissions that are granted to the team." + ] + }, + "counts": { + "type": "object", + "properties": { + "member_count": { + "type": "integer", + "description": "Total count of members of the team.", + "x-description": [ + "Total count of members of the team." + ] + }, + "project_count": { + "type": "integer", + "description": "Total count of projects that the team has access to.", + "x-description": [ + "Total count of projects that the team has access to." + ] + } + }, + "x-isDateTime": false + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the team was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the team was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the team was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the team was last updated." + ] + } + }, + "x-examples": { + "example-1": { + "id": "01FVMKN9KHVWWVY488AVKDWHR3", + "organization_id": "01EY8BWRSQ56EY1TDC32PARAJS", + "counts": { + "member_count": 12, + "project_count": 5 + }, + "label": "Contractors", + "created_at": "2021-05-24T07:20:35.683264Z", + "updated_at": "2021-05-24T07:20:35.683264Z", + "project_permissions": [ + "viewer", + "staging:contributor", + "development:admin" + ] + } + } + }, + "TeamMember": { + "type": "object", + "properties": { + "team_id": { + "type": "string", + "format": "ulid", + "description": "The ID of the team.", + "x-isDateTime": false, + "x-description": [ + "The ID of the team." + ] + }, + "user_id": { + "type": "string", + "format": "uuid", + "description": "The ID of the user.", + "x-isDateTime": false, + "x-description": [ + "The ID of the user." + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the team member was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the team member was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the team member was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the team member was last updated." + ] + } + } + }, + "UserReference": { + "description": "The referenced user, or null if it no longer exists.", + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of the user.", + "x-isDateTime": false, + "x-description": [ + "The ID of the user." + ] + }, + "username": { + "type": "string", + "description": "The user's username.", + "x-isDateTime": false, + "x-description": [ + "The user's username." + ] + }, + "email": { + "type": "string", + "format": "email", + "description": "The user's email address.", + "x-isDateTime": false, + "x-description": [ + "The user's email address." + ] + }, + "first_name": { + "type": "string", + "description": "The user's first name.", + "x-isDateTime": false, + "x-description": [ + "The user's first name." + ] + }, + "last_name": { + "type": "string", + "description": "The user's last name.", + "x-isDateTime": false, + "x-description": [ + "The user's last name." + ] + }, + "picture": { + "type": "string", + "format": "uri", + "description": "The user's picture.", + "x-isDateTime": false, + "x-description": [ + "The user's picture." + ] + }, + "mfa_enabled": { + "type": "boolean", + "description": "Whether the user has enabled MFA. Note: the built-in MFA feature may not be necessary if the user is linked to a mandatory SSO provider that itself supports MFA (see \"sso_enabled\\\").", + "x-isDateTime": false, + "x-description": [ + "Whether the user has enabled MFA. Note: the built-in MFA feature may not be necessary if the user is linked to a", + "mandatory SSO provider that itself supports MFA (see \"sso_enabled\\\")." + ] + }, + "sso_enabled": { + "type": "boolean", + "description": "Whether the user is linked to a mandatory SSO provider.", + "x-isDateTime": false, + "x-description": [ + "Whether the user is linked to a mandatory SSO provider." + ] + } + }, + "x-examples": { + "example-1": { + "email": "hello@platform.sh", + "first_name": "Hello", + "id": "d81c8ee2-44b3-429f-b944-a33ad7437690", + "last_name": "World", + "picture": "https://accounts.platform.sh/profiles/blimp_profile/themes/platformsh_theme/images/mail/logo.png", + "username": "platform-sh", + "mfa_enabled": true, + "sso_enabled": true + } + }, + "x-description": [ + "The referenced user, or null if it no longer exists." + ] + }, + "TeamReference": { + "description": "The referenced team, or null if it no longer exists.", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "ulid", + "description": "The ID of the team.", + "x-isDateTime": false, + "x-description": [ + "The ID of the team." + ] + }, + "organization_id": { + "type": "string", + "format": "ulid", + "description": "The ID of the parent organization.", + "x-isDateTime": false, + "x-description": [ + "The ID of the parent organization." + ] + }, + "label": { + "type": "string", + "description": "The human-readable label of the team.", + "x-isDateTime": false, + "x-description": [ + "The human-readable label of the team." + ] + }, + "project_permissions": { + "type": "array", + "description": "Project permissions that are granted to the team.", + "items": { + "type": "string", + "enum": [ + "admin", + "viewer", + "development:admin", + "development:contributor", + "development:viewer", + "staging:admin", + "staging:contributor", + "staging:viewer", + "production:admin", + "production:contributor", + "production:viewer" + ] + }, + "x-isDateTime": false, + "x-description": [ + "Project permissions that are granted to the team." + ] + }, + "counts": { + "type": "object", + "properties": { + "member_count": { + "type": "integer", + "description": "Total count of members of the team.", + "x-description": [ + "Total count of members of the team." + ] + }, + "project_count": { + "type": "integer", + "description": "Total count of projects that the team has access to.", + "x-description": [ + "Total count of projects that the team has access to." + ] + } + }, + "x-isDateTime": false + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the team was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the team was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the team was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the team was last updated." + ] + } + }, + "x-examples": { + "example-1": { + "id": "01FVMKN9KHVWWVY488AVKDWHR3", + "organization_id": "01EY8BWRSQ56EY1TDC32PARAJS", + "counts": { + "member_count": 12, + "project_count": 5 + }, + "label": "Contractors", + "project_permissions": [ + "viewer", + "staging:contributor", + "development:admin" + ], + "created_at": "2021-05-24T07:20:35.683264Z", + "updated_at": "2021-05-24T07:20:35.683264Z" + } + }, + "x-description": [ + "The referenced team, or null if it no longer exists." + ] + }, + "DateTimeFilter": { + "type": "object", + "properties": { + "eq": { + "type": "string", + "description": "Equal", + "x-isDateTime": false, + "x-description": [ + "Equal" + ] + }, + "ne": { + "type": "string", + "description": "Not equal", + "x-isDateTime": false, + "x-description": [ + "Not equal" + ] + }, + "between": { + "type": "string", + "description": "Between (comma-separated list)", + "x-isDateTime": false, + "x-description": [ + "Between (comma-separated list)" + ] + }, + "gt": { + "type": "string", + "description": "Greater than", + "x-isDateTime": false, + "x-description": [ + "Greater than" + ] + }, + "gte": { + "type": "string", + "description": "Greater than or equal", + "x-isDateTime": false, + "x-description": [ + "Greater than or equal" + ] + }, + "lt": { + "type": "string", + "description": "Less than", + "x-isDateTime": false, + "x-description": [ + "Less than" + ] + }, + "lte": { + "type": "string", + "description": "Less than or equal", + "x-isDateTime": false, + "x-description": [ + "Less than or equal" + ] + } + } + }, + "StringFilter": { + "type": "object", + "properties": { + "eq": { + "type": "string", + "description": "Equal", + "x-isDateTime": false, + "x-description": [ + "Equal" + ] + }, + "ne": { + "type": "string", + "description": "Not equal", + "x-isDateTime": false, + "x-description": [ + "Not equal" + ] + }, + "in": { + "type": "string", + "description": "In (comma-separated list)", + "x-isDateTime": false, + "x-description": [ + "In (comma-separated list)" + ] + }, + "nin": { + "type": "string", + "description": "Not in (comma-separated list)", + "x-isDateTime": false, + "x-description": [ + "Not in (comma-separated list)" + ] + }, + "between": { + "type": "string", + "description": "Between (comma-separated list)", + "x-isDateTime": false, + "x-description": [ + "Between (comma-separated list)" + ] + }, + "contains": { + "type": "string", + "description": "Contains", + "x-isDateTime": false, + "x-description": [ + "Contains" + ] + }, + "starts": { + "type": "string", + "description": "Starts with", + "x-isDateTime": false, + "x-description": [ + "Starts with" + ] + }, + "ends": { + "type": "string", + "description": "Ends with", + "x-isDateTime": false, + "x-description": [ + "Ends with" + ] + } + } + }, + "AcceptedResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "title": "Status text", + "description": "The status text of the response", + "x-isDateTime": false, + "x-description": [ + "The status text of the response" + ] + }, + "code": { + "type": "integer", + "title": "Status code", + "description": "The status code of the response", + "x-isDateTime": false, + "x-description": [ + "The status code of the response" + ] + } + }, + "required": [ + "status", + "code" + ], + "additionalProperties": false + }, + "Activity": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Activity Identifier", + "description": "The identifier of Activity", + "x-isDateTime": false, + "x-description": [ + "The identifier of Activity" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Type", + "description": "The type of the activity", + "x-isDateTime": false, + "x-description": [ + "The type of the activity" + ] + }, + "parameters": { + "type": "object", + "title": "Parameters", + "description": "The parameters of the activity", + "x-isDateTime": false, + "x-description": [ + "The parameters of the activity" + ] + }, + "project": { + "type": "string", + "title": "Project", + "description": "The project the activity belongs to", + "x-isDateTime": false, + "x-description": [ + "The project the activity belongs to" + ] + }, + "integration": { + "type": "string", + "title": "Integration", + "description": "The integration the activity belongs to", + "x-isDateTime": false, + "x-description": [ + "The integration the activity belongs to" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments related to the activity", + "x-isDateTime": false, + "x-description": [ + "The environments related to the activity" + ] + }, + "state": { + "type": "string", + "enum": [ + "cancelled", + "complete", + "in_progress", + "pending", + "scheduled", + "staged" + ], + "title": "State", + "description": "The state of the activity", + "x-isDateTime": false, + "x-description": [ + "The state of the activity" + ] + }, + "result": { + "type": "string", + "enum": [ + "failure", + "success" + ], + "nullable": true, + "title": "Result", + "description": "The result of the activity", + "x-isDateTime": false, + "x-description": [ + "The result of the activity" + ] + }, + "started_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Start date", + "description": "The start date of the activity", + "x-isDateTime": true, + "x-description": [ + "The start date of the activity" + ] + }, + "completed_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Completion date", + "description": "The completion date of the activity", + "x-isDateTime": true, + "x-description": [ + "The completion date of the activity" + ] + }, + "completion_percent": { + "type": "integer", + "title": "Completion percentage", + "description": "The completion percentage of the activity", + "x-isDateTime": false, + "x-description": [ + "The completion percentage of the activity" + ] + }, + "cancelled_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Cancellation date", + "description": "The Cancellation date of the activity", + "x-isDateTime": true, + "x-description": [ + "The Cancellation date of the activity" + ] + }, + "timings": { + "type": "object", + "additionalProperties": { + "type": "number", + "format": "float" + }, + "title": "Timings", + "description": "Timings related to different phases of the activity", + "x-isDateTime": false, + "x-description": [ + "Timings related to different phases of the activity" + ] + }, + "log": { + "type": "string", + "title": "Log", + "description": "The log of the activity", + "deprecated": true, + "x-stability": "DEPRECATED", + "x-isDateTime": false, + "x-description": [ + "The log of the activity" + ] + }, + "payload": { + "type": "object", + "title": "Payload", + "description": "The payload of the activity", + "x-isDateTime": false, + "x-description": [ + "The payload of the activity" + ] + }, + "description": { + "type": "string", + "nullable": true, + "title": "Activity HTML description", + "description": "The description of the activity, formatted with HTML", + "x-isDateTime": false, + "x-description": [ + "The description of the activity, formatted with HTML" + ] + }, + "text": { + "type": "string", + "nullable": true, + "title": "Activity text description", + "description": "The description of the activity, formatted as plain text", + "x-isDateTime": false, + "x-description": [ + "The description of the activity, formatted as plain text" + ] + }, + "expires_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Expiration date", + "description": "The date at which the activity will expire", + "x-isDateTime": true, + "x-description": [ + "The date at which the activity will expire" + ] + }, + "commands": { + "type": "array", + "items": { + "type": "object", + "properties": { + "app": { + "type": "string", + "title": "Application", + "description": "" + }, + "type": { + "type": "string", + "title": "Type", + "description": "" + }, + "exit_code": { + "type": "integer", + "title": "Exit status code", + "description": "" + } + }, + "required": [ + "app", + "type", + "exit_code" + ], + "additionalProperties": false + }, + "title": "Commands", + "description": "The commands of the activity", + "x-isDateTime": false, + "x-description": [ + "The commands of the activity" + ] + } + }, + "required": [ + "id", + "created_at", + "updated_at", + "type", + "parameters", + "project", + "state", + "result", + "started_at", + "completed_at", + "completion_percent", + "cancelled_at", + "timings", + "log", + "payload", + "description", + "text", + "expires_at", + "commands" + ], + "additionalProperties": false + }, + "ActivityCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Activity" + } + }, + "Backup": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Backup Identifier", + "description": "The identifier of Backup", + "x-isDateTime": false, + "x-description": [ + "The identifier of Backup" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "status": { + "type": "string", + "enum": [ + "CREATED", + "DELETING" + ], + "title": "Status", + "description": "The status of the backup", + "x-isDateTime": false, + "x-description": [ + "The status of the backup" + ] + }, + "expires_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Expires At", + "description": "Expiration date of the backup", + "x-isDateTime": true, + "x-description": [ + "Expiration date of the backup" + ] + }, + "index": { + "type": "integer", + "nullable": true, + "title": "Index", + "description": "The index of this automated backup", + "x-isDateTime": false, + "x-description": [ + "The index of this automated backup" + ] + }, + "commit_id": { + "type": "string", + "title": "Commit ID", + "description": "The ID of the code commit attached to the backup", + "x-isDateTime": false, + "x-description": [ + "The ID of the code commit attached to the backup" + ] + }, + "environment": { + "type": "string", + "title": "Environment", + "description": "The environment the backup belongs to", + "x-isDateTime": false, + "x-description": [ + "The environment the backup belongs to" + ] + }, + "safe": { + "type": "boolean", + "title": "Safe", + "description": "Whether this backup was taken in a safe way", + "x-isDateTime": false, + "x-description": [ + "Whether this backup was taken in a safe way" + ] + }, + "size_of_volumes": { + "type": "integer", + "nullable": true, + "title": "Size of volumes", + "description": "Total size of volumes backed up", + "x-isDateTime": false, + "x-description": [ + "Total size of volumes backed up" + ] + }, + "size_used": { + "type": "integer", + "nullable": true, + "title": "Size used", + "description": "Total size of space used on volumes backed up", + "x-isDateTime": false, + "x-description": [ + "Total size of space used on volumes backed up" + ] + }, + "deployment": { + "type": "string", + "nullable": true, + "title": "Deployment", + "description": "The current deployment at the time of backup", + "x-isDateTime": false, + "x-description": [ + "The current deployment at the time of backup" + ] + }, + "restorable": { + "type": "boolean", + "title": "Is restorable", + "description": "Whether the backup is restorable", + "x-isDateTime": false, + "x-description": [ + "Whether the backup is restorable" + ] + }, + "automated": { + "type": "boolean", + "title": "Is automated", + "description": "Whether the backup is automated", + "x-isDateTime": false, + "x-description": [ + "Whether the backup is automated" + ] + } + }, + "required": [ + "id", + "created_at", + "updated_at", + "attributes", + "status", + "expires_at", + "index", + "commit_id", + "environment", + "safe", + "size_of_volumes", + "size_used", + "deployment", + "restorable", + "automated" + ], + "additionalProperties": false + }, + "BackupCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Backup" + } + }, + "BitbucketIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "BitbucketIntegration Identifier", + "description": "The identifier of BitbucketIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of BitbucketIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "app_credentials": { + "type": "object", + "properties": { + "key": { + "type": "string", + "title": "OAuth consumer key.", + "description": "The OAuth consumer key.", + "x-description": [ + "The OAuth consumer key." + ] + } + }, + "required": [ + "key" + ], + "additionalProperties": false, + "nullable": true, + "title": "OAuth2 consumer", + "description": "The OAuth2 consumer information (optional).", + "x-isDateTime": false, + "x-description": [ + "The OAuth2 consumer information (optional)." + ] + }, + "addon_credentials": { + "type": "object", + "properties": { + "addon_key": { + "type": "string", + "title": "Addon key", + "description": "The addon key (public identifier).", + "x-description": [ + "The addon key (public identifier)." + ] + }, + "client_key": { + "type": "string", + "title": "Client key", + "description": "The client key (public identifier).", + "x-description": [ + "The client key (public identifier)." + ] + } + }, + "required": [ + "addon_key", + "client_key" + ], + "additionalProperties": false, + "nullable": true, + "title": "Addon credential", + "description": "The addon credential information (optional).", + "x-isDateTime": false, + "x-description": [ + "The addon credential information (optional)." + ] + }, + "repository": { + "type": "string", + "title": "Bitbucket repository", + "description": "The Bitbucket repository (in the form `user/repo`).", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket repository (in the form `user/repo`)." + ] + }, + "build_pull_requests": { + "type": "boolean", + "title": "Build pull requests", + "description": "Whether or not to build pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build pull requests." + ] + }, + "pull_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone parent data", + "description": "Whether or not to clone parent data when building merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building merge requests." + ] + }, + "resync_pull_requests": { + "type": "boolean", + "title": "Sync environment data", + "description": "Whether or not pull request environment data should be re-synced on every build.", + "x-isDateTime": false, + "x-description": [ + "Whether or not pull request environment data should be re-synced on every build." + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "fetch_branches", + "prune_branches", + "environment_init_resources", + "repository", + "build_pull_requests", + "pull_requests_clone_parent_data", + "resync_pull_requests" + ], + "additionalProperties": false + }, + "BitbucketIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "app_credentials": { + "type": "object", + "properties": { + "key": { + "type": "string", + "title": "OAuth consumer key.", + "description": "The OAuth consumer key.", + "x-description": [ + "The OAuth consumer key." + ] + }, + "secret": { + "type": "string", + "title": "OAuth consumer secret.", + "description": "The OAuth consumer secret.", + "x-description": [ + "The OAuth consumer secret." + ] + } + }, + "required": [ + "key", + "secret" + ], + "additionalProperties": false, + "nullable": true, + "title": "OAuth2 consumer", + "description": "The OAuth2 consumer information (optional).", + "x-isDateTime": false, + "x-description": [ + "The OAuth2 consumer information (optional)." + ] + }, + "addon_credentials": { + "type": "object", + "properties": { + "addon_key": { + "type": "string", + "title": "Addon key", + "description": "The addon key (public identifier).", + "x-description": [ + "The addon key (public identifier)." + ] + }, + "client_key": { + "type": "string", + "title": "Client key", + "description": "The client key (public identifier).", + "x-description": [ + "The client key (public identifier)." + ] + }, + "shared_secret": { + "type": "string", + "title": "Client secret", + "description": "The secret of the client.", + "x-description": [ + "The secret of the client." + ] + } + }, + "required": [ + "addon_key", + "client_key", + "shared_secret" + ], + "additionalProperties": false, + "nullable": true, + "title": "Addon credential", + "description": "The addon credential information (optional).", + "x-isDateTime": false, + "x-description": [ + "The addon credential information (optional)." + ] + }, + "repository": { + "type": "string", + "title": "Bitbucket repository", + "description": "The Bitbucket repository (in the form `user/repo`).", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket repository (in the form `user/repo`)." + ] + }, + "build_pull_requests": { + "type": "boolean", + "title": "Build pull requests", + "description": "Whether or not to build pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build pull requests." + ] + }, + "pull_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone parent data", + "description": "Whether or not to clone parent data when building merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building merge requests." + ] + }, + "resync_pull_requests": { + "type": "boolean", + "title": "Sync environment data", + "description": "Whether or not pull request environment data should be re-synced on every build.", + "x-isDateTime": false, + "x-description": [ + "Whether or not pull request environment data should be re-synced on every build." + ] + } + }, + "required": [ + "type", + "repository" + ], + "additionalProperties": false + }, + "BitbucketIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "app_credentials": { + "type": "object", + "properties": { + "key": { + "type": "string", + "title": "OAuth consumer key.", + "description": "The OAuth consumer key.", + "x-description": [ + "The OAuth consumer key." + ] + }, + "secret": { + "type": "string", + "title": "OAuth consumer secret.", + "description": "The OAuth consumer secret.", + "x-description": [ + "The OAuth consumer secret." + ] + } + }, + "required": [ + "key", + "secret" + ], + "additionalProperties": false, + "nullable": true, + "title": "OAuth2 consumer", + "description": "The OAuth2 consumer information (optional).", + "x-isDateTime": false, + "x-description": [ + "The OAuth2 consumer information (optional)." + ] + }, + "addon_credentials": { + "type": "object", + "properties": { + "addon_key": { + "type": "string", + "title": "Addon key", + "description": "The addon key (public identifier).", + "x-description": [ + "The addon key (public identifier)." + ] + }, + "client_key": { + "type": "string", + "title": "Client key", + "description": "The client key (public identifier).", + "x-description": [ + "The client key (public identifier)." + ] + }, + "shared_secret": { + "type": "string", + "title": "Client secret", + "description": "The secret of the client.", + "x-description": [ + "The secret of the client." + ] + } + }, + "required": [ + "addon_key", + "client_key", + "shared_secret" + ], + "additionalProperties": false, + "nullable": true, + "title": "Addon credential", + "description": "The addon credential information (optional).", + "x-isDateTime": false, + "x-description": [ + "The addon credential information (optional)." + ] + }, + "repository": { + "type": "string", + "title": "Bitbucket repository", + "description": "The Bitbucket repository (in the form `user/repo`).", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket repository (in the form `user/repo`)." + ] + }, + "build_pull_requests": { + "type": "boolean", + "title": "Build pull requests", + "description": "Whether or not to build pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build pull requests." + ] + }, + "pull_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone parent data", + "description": "Whether or not to clone parent data when building merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building merge requests." + ] + }, + "resync_pull_requests": { + "type": "boolean", + "title": "Sync environment data", + "description": "Whether or not pull request environment data should be re-synced on every build.", + "x-isDateTime": false, + "x-description": [ + "Whether or not pull request environment data should be re-synced on every build." + ] + } + }, + "required": [ + "type", + "repository" + ], + "additionalProperties": false + }, + "BitbucketServerIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "BitbucketServerIntegration Identifier", + "description": "The identifier of BitbucketServerIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of BitbucketServerIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "url": { + "type": "string", + "title": "URL", + "description": "The base URL of the Bitbucket Server installation.", + "x-isDateTime": false, + "x-description": [ + "The base URL of the Bitbucket Server installation." + ] + }, + "username": { + "type": "string", + "title": "Username", + "description": "The Bitbucket Server user.", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server user." + ] + }, + "project": { + "type": "string", + "title": "Project", + "description": "The Bitbucket Server project", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server project" + ] + }, + "repository": { + "type": "string", + "title": "Repository", + "description": "The Bitbucket Server repository", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server repository" + ] + }, + "build_pull_requests": { + "type": "boolean", + "title": "Build Pull Requests", + "description": "Whether or not to build pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build pull requests." + ] + }, + "pull_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone Parent Data", + "description": "Whether or not to clone parent data when building merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building merge requests." + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "fetch_branches", + "prune_branches", + "environment_init_resources", + "url", + "username", + "project", + "repository", + "build_pull_requests", + "pull_requests_clone_parent_data" + ], + "additionalProperties": false + }, + "BitbucketServerIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "url": { + "type": "string", + "title": "URL", + "description": "The base URL of the Bitbucket Server installation.", + "x-isDateTime": false, + "x-description": [ + "The base URL of the Bitbucket Server installation." + ] + }, + "username": { + "type": "string", + "title": "Username", + "description": "The Bitbucket Server user.", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server user." + ] + }, + "token": { + "type": "string", + "title": "Token", + "description": "The Bitbucket Server personal access token.", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server personal access token." + ] + }, + "project": { + "type": "string", + "title": "Project", + "description": "The Bitbucket Server project", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server project" + ] + }, + "repository": { + "type": "string", + "title": "Repository", + "description": "The Bitbucket Server repository", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server repository" + ] + }, + "build_pull_requests": { + "type": "boolean", + "title": "Build Pull Requests", + "description": "Whether or not to build pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build pull requests." + ] + }, + "pull_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone Parent Data", + "description": "Whether or not to clone parent data when building merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building merge requests." + ] + } + }, + "required": [ + "type", + "url", + "username", + "token", + "project", + "repository" + ], + "additionalProperties": false + }, + "BitbucketServerIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "url": { + "type": "string", + "title": "URL", + "description": "The base URL of the Bitbucket Server installation.", + "x-isDateTime": false, + "x-description": [ + "The base URL of the Bitbucket Server installation." + ] + }, + "username": { + "type": "string", + "title": "Username", + "description": "The Bitbucket Server user.", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server user." + ] + }, + "token": { + "type": "string", + "title": "Token", + "description": "The Bitbucket Server personal access token.", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server personal access token." + ] + }, + "project": { + "type": "string", + "title": "Project", + "description": "The Bitbucket Server project", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server project" + ] + }, + "repository": { + "type": "string", + "title": "Repository", + "description": "The Bitbucket Server repository", + "x-isDateTime": false, + "x-description": [ + "The Bitbucket Server repository" + ] + }, + "build_pull_requests": { + "type": "boolean", + "title": "Build Pull Requests", + "description": "Whether or not to build pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build pull requests." + ] + }, + "pull_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone Parent Data", + "description": "Whether or not to clone parent data when building merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building merge requests." + ] + } + }, + "required": [ + "type", + "url", + "username", + "token", + "project", + "repository" + ], + "additionalProperties": false + }, + "BlackfireIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "BlackfireIntegration Identifier", + "description": "The identifier of BlackfireIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of BlackfireIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "environments_credentials": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "server_uuid": { + "type": "string", + "title": "Server UUID", + "description": "The environment server UUID" + }, + "server_token": { + "type": "string", + "title": "Server Token", + "description": "Environment server token" + } + }, + "required": [ + "server_uuid", + "server_token" + ], + "additionalProperties": false + }, + "title": "Environments Credentials", + "description": "Blackfire environments credentials", + "x-isDateTime": false, + "x-description": [ + "Blackfire environments credentials" + ] + }, + "continuous_profiling": { + "type": "boolean", + "title": "Continuous Profiling", + "description": "Whether continuous profiling is enabled for the project", + "x-isDateTime": false, + "x-description": [ + "Whether continuous profiling is enabled for the project" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "environments_credentials", + "continuous_profiling" + ], + "additionalProperties": false + }, + "BlackfireIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "BlackfireIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "Blob": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Blob Identifier", + "description": "The identifier of Blob", + "x-isDateTime": false, + "x-description": [ + "The identifier of Blob" + ] + }, + "sha": { + "type": "string", + "title": "SHA", + "description": "The identifier of the tag", + "x-isDateTime": false, + "x-description": [ + "The identifier of the tag" + ] + }, + "size": { + "type": "integer", + "title": "Size", + "description": "The size of the blob", + "x-isDateTime": false, + "x-description": [ + "The size of the blob" + ] + }, + "encoding": { + "type": "string", + "enum": [ + "base64", + "utf-8" + ], + "title": "Encoding", + "description": "The encoding of the contents", + "x-isDateTime": false, + "x-description": [ + "The encoding of the contents" + ] + }, + "content": { + "type": "string", + "title": "Content", + "description": "The contents", + "x-isDateTime": false, + "x-description": [ + "The contents" + ] + } + }, + "required": [ + "id", + "sha", + "size", + "encoding", + "content" + ], + "additionalProperties": false + }, + "Certificate": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Certificate Identifier", + "description": "The identifier of Certificate", + "x-isDateTime": false, + "x-description": [ + "The identifier of Certificate" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "certificate": { + "type": "string", + "title": "Certificate", + "description": "The PEM-encoded certificate", + "x-isDateTime": false, + "x-description": [ + "The PEM-encoded certificate" + ] + }, + "chain": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Certificate chain", + "description": "The certificate chain", + "x-isDateTime": false, + "x-description": [ + "The certificate chain" + ] + }, + "is_provisioned": { + "type": "boolean", + "title": "Is Provisioned", + "description": "Whether this certificate is automatically provisioned", + "x-isDateTime": false, + "x-description": [ + "Whether this certificate is automatically provisioned" + ] + }, + "is_invalid": { + "type": "boolean", + "title": "Is Invalid", + "description": "Whether this certificate should be skipped during provisioning", + "x-isDateTime": false, + "x-description": [ + "Whether this certificate should be skipped during provisioning" + ] + }, + "is_root": { + "type": "boolean", + "title": "Is Root", + "description": "Whether this certificate is root type", + "x-isDateTime": false, + "x-description": [ + "Whether this certificate is root type" + ] + }, + "domains": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Domains", + "description": "The domains covered by this certificate", + "x-isDateTime": false, + "x-description": [ + "The domains covered by this certificate" + ] + }, + "auth_type": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Authentication Type", + "description": "The type of authentication the certificate supports", + "x-isDateTime": false, + "x-description": [ + "The type of authentication the certificate supports" + ] + }, + "issuer": { + "type": "array", + "items": { + "type": "object", + "properties": { + "oid": { + "type": "string", + "title": "OID", + "description": "The OID of the attribute" + }, + "alias": { + "type": "string", + "nullable": true, + "title": "Alias", + "description": "The alias of the attribute, if known" + }, + "value": { + "type": "string", + "title": "Value", + "description": "The value" + } + }, + "required": [ + "oid", + "alias", + "value" + ], + "additionalProperties": false + }, + "title": "Issuer", + "description": "The issuer of the certificate", + "x-isDateTime": false, + "x-description": [ + "The issuer of the certificate" + ] + }, + "expires_at": { + "type": "string", + "format": "date-time", + "title": "Expiration date", + "description": "Expiration date", + "x-isDateTime": true, + "x-description": [ + "Expiration date" + ] + } + }, + "required": [ + "id", + "created_at", + "updated_at", + "certificate", + "chain", + "is_provisioned", + "is_invalid", + "is_root", + "domains", + "auth_type", + "issuer", + "expires_at" + ], + "additionalProperties": false + }, + "CertificateCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Certificate" + } + }, + "CertificateCreateInput": { + "type": "object", + "properties": { + "certificate": { + "type": "string", + "title": "Certificate", + "description": "The PEM-encoded certificate", + "x-isDateTime": false, + "x-description": [ + "The PEM-encoded certificate" + ] + }, + "key": { + "type": "string", + "title": "Private Key", + "description": "The PEM-encoded private key", + "x-isDateTime": false, + "x-description": [ + "The PEM-encoded private key" + ] + }, + "chain": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Certificate chain", + "description": "The certificate chain", + "x-isDateTime": false, + "x-description": [ + "The certificate chain" + ] + }, + "is_invalid": { + "type": "boolean", + "title": "Is Invalid", + "description": "Whether this certificate should be skipped during provisioning", + "x-isDateTime": false, + "x-description": [ + "Whether this certificate should be skipped during provisioning" + ] + } + }, + "required": [ + "certificate", + "key" + ], + "additionalProperties": false + }, + "CertificatePatch": { + "type": "object", + "properties": { + "chain": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Certificate chain", + "description": "The certificate chain", + "x-isDateTime": false, + "x-description": [ + "The certificate chain" + ] + }, + "is_invalid": { + "type": "boolean", + "title": "Is Invalid", + "description": "Whether this certificate should be skipped during provisioning", + "x-isDateTime": false, + "x-description": [ + "Whether this certificate should be skipped during provisioning" + ] + } + }, + "additionalProperties": false + }, + "CertificateProvisioner": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "CertificateProvisioner Identifier", + "description": "The identifier of CertificateProvisioner", + "x-isDateTime": false, + "x-description": [ + "The identifier of CertificateProvisioner" + ] + }, + "directory_url": { + "type": "string", + "title": "ACME directory url", + "description": "The URL to the ACME directory", + "x-isDateTime": false, + "x-description": [ + "The URL to the ACME directory" + ] + }, + "email": { + "type": "string", + "title": "Contacted email address", + "description": "The email address for contact information", + "x-isDateTime": false, + "x-description": [ + "The email address for contact information" + ] + }, + "eab_kid": { + "type": "string", + "nullable": true, + "title": "EAB Key identifier", + "description": "The key identifier for Entity Attestation Binding", + "x-isDateTime": false, + "x-description": [ + "The key identifier for Entity Attestation Binding" + ] + }, + "eab_hmac_key": { + "type": "string", + "nullable": true, + "title": "EAB HMAC Key", + "description": "The Keyed-'Hashing Message Authentication Code' for Entity Attestation Binding", + "x-isDateTime": false, + "x-description": [ + "The Keyed-'Hashing Message Authentication Code' for Entity Attestation Binding" + ] + } + }, + "required": [ + "id", + "directory_url", + "email", + "eab_kid", + "eab_hmac_key" + ], + "additionalProperties": false + }, + "CertificateProvisionerCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CertificateProvisioner" + } + }, + "CertificateProvisionerPatch": { + "type": "object", + "properties": { + "directory_url": { + "type": "string", + "title": "ACME directory url", + "description": "The URL to the ACME directory", + "x-isDateTime": false, + "x-description": [ + "The URL to the ACME directory" + ] + }, + "email": { + "type": "string", + "title": "Contacted email address", + "description": "The email address for contact information", + "x-isDateTime": false, + "x-description": [ + "The email address for contact information" + ] + }, + "eab_kid": { + "type": "string", + "nullable": true, + "title": "EAB Key identifier", + "description": "The key identifier for Entity Attestation Binding", + "x-isDateTime": false, + "x-description": [ + "The key identifier for Entity Attestation Binding" + ] + }, + "eab_hmac_key": { + "type": "string", + "nullable": true, + "title": "EAB HMAC Key", + "description": "The Keyed-'Hashing Message Authentication Code' for Entity Attestation Binding", + "x-isDateTime": false, + "x-description": [ + "The Keyed-'Hashing Message Authentication Code' for Entity Attestation Binding" + ] + } + }, + "additionalProperties": false + }, + "Commit": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Commit Identifier", + "description": "The identifier of Commit", + "x-isDateTime": false, + "x-description": [ + "The identifier of Commit" + ] + }, + "sha": { + "type": "string", + "title": "SHA", + "description": "The identifier of the commit", + "x-isDateTime": false, + "x-description": [ + "The identifier of the commit" + ] + }, + "author": { + "type": "object", + "properties": { + "date": { + "type": "string", + "format": "date-time", + "title": "Date", + "description": "The time of the author or committer", + "x-description": [ + "The time of the author or committer" + ] + }, + "name": { + "type": "string", + "title": "Name", + "description": "The name of the author or committer", + "x-description": [ + "The name of the author or committer" + ] + }, + "email": { + "type": "string", + "title": "Email", + "description": "The email of the author or committer", + "x-description": [ + "The email of the author or committer" + ] + } + }, + "required": [ + "date", + "name", + "email" + ], + "additionalProperties": false, + "title": "Author", + "description": "The information about the author", + "x-isDateTime": false, + "x-description": [ + "The information about the author" + ] + }, + "committer": { + "type": "object", + "properties": { + "date": { + "type": "string", + "format": "date-time", + "title": "Date", + "description": "The time of the author or committer", + "x-description": [ + "The time of the author or committer" + ] + }, + "name": { + "type": "string", + "title": "Name", + "description": "The name of the author or committer", + "x-description": [ + "The name of the author or committer" + ] + }, + "email": { + "type": "string", + "title": "Email", + "description": "The email of the author or committer", + "x-description": [ + "The email of the author or committer" + ] + } + }, + "required": [ + "date", + "name", + "email" + ], + "additionalProperties": false, + "title": "Committer", + "description": "The information about the committer", + "x-isDateTime": false, + "x-description": [ + "The information about the committer" + ] + }, + "message": { + "type": "string", + "title": "Message", + "description": "The commit message", + "x-isDateTime": false, + "x-description": [ + "The commit message" + ] + }, + "tree": { + "type": "string", + "title": "Tree identifier", + "description": "The identifier of the tree", + "x-isDateTime": false, + "x-description": [ + "The identifier of the tree" + ] + }, + "parents": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Parent identifiers", + "description": "The identifiers of the parents of the commit", + "x-isDateTime": false, + "x-description": [ + "The identifiers of the parents of the commit" + ] + } + }, + "required": [ + "id", + "sha", + "author", + "committer", + "message", + "tree", + "parents" + ], + "additionalProperties": false + }, + "DedicatedDeploymentTarget": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "DedicatedDeploymentTarget Identifier", + "description": "The identifier of DedicatedDeploymentTarget", + "x-isDateTime": false, + "x-description": [ + "The identifier of DedicatedDeploymentTarget" + ] + }, + "type": { + "type": "string", + "enum": [ + "dedicated", + "enterprise", + "local" + ], + "title": "Deployment target type", + "description": "The type of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The type of the deployment target." + ] + }, + "name": { + "type": "string", + "title": "Deployment target name", + "description": "The name of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The name of the deployment target." + ] + }, + "deploy_host": { + "type": "string", + "nullable": true, + "title": "Host", + "description": "The host to deploy to.", + "x-isDateTime": false, + "x-description": [ + "The host to deploy to." + ] + }, + "deploy_port": { + "type": "integer", + "nullable": true, + "title": "Port", + "description": "The port to deploy to.", + "x-isDateTime": false, + "x-description": [ + "The port to deploy to." + ] + }, + "ssh_host": { + "type": "string", + "nullable": true, + "title": "SSH Host", + "description": "The host to use to SSH to app containers.", + "x-isDateTime": false, + "x-description": [ + "The host to use to SSH to app containers." + ] + }, + "hosts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true, + "title": "Host identifier", + "description": "The identifier of the host." + }, + "type": { + "type": "string", + "enum": [ + "core", + "satellite" + ], + "title": "Deployment type", + "description": "The type of the deployment to this host." + }, + "services": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "title": "Assigned services", + "description": "The services assigned to this host" + } + }, + "required": [ + "id", + "type", + "services" + ], + "additionalProperties": false + }, + "nullable": true, + "title": "Hosts", + "description": "The hosts of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The hosts of the deployment target." + ] + }, + "auto_mounts": { + "type": "boolean", + "title": "Auto Mounts", + "description": "Whether to take application mounts from the pushed data or the deployment target.", + "x-isDateTime": false, + "x-description": [ + "Whether to take application mounts from the pushed data or the deployment target." + ] + }, + "excluded_mounts": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Mounts", + "description": "Directories that should not be mounted", + "x-isDateTime": false, + "x-description": [ + "Directories that should not be mounted" + ] + }, + "enforced_mounts": { + "type": "object", + "title": "Enforced Mounts", + "description": "Mounts which are always injected into pushed (e.g. enforce /var/log to be a local mount).", + "x-isDateTime": false, + "x-description": [ + "Mounts which are always injected into pushed (e.g. enforce /var/log to be a local mount)." + ] + }, + "auto_crons": { + "type": "boolean", + "title": "Auto Crons", + "description": "Whether to take application crons from the pushed data or the deployment target.", + "x-isDateTime": false, + "x-description": [ + "Whether to take application crons from the pushed data or the deployment target." + ] + }, + "auto_nginx": { + "type": "boolean", + "title": "Auto Nginx", + "description": "Whether to take application crons from the pushed data or the deployment target.", + "x-isDateTime": false, + "x-description": [ + "Whether to take application crons from the pushed data or the deployment target." + ] + }, + "maintenance_mode": { + "type": "boolean", + "title": "Maintenance Mode", + "description": "Whether to perform deployments or not", + "x-isDateTime": false, + "x-description": [ + "Whether to perform deployments or not" + ] + }, + "guardrails_phase": { + "type": "integer", + "title": "Guardrails Phase", + "description": "which phase of guardrails are we in", + "x-isDateTime": false, + "x-description": [ + "which phase of guardrails are we in" + ] + } + }, + "required": [ + "type", + "name", + "deploy_host", + "deploy_port", + "ssh_host", + "hosts", + "auto_mounts", + "excluded_mounts", + "enforced_mounts", + "auto_crons", + "auto_nginx", + "maintenance_mode", + "guardrails_phase" + ], + "additionalProperties": false + }, + "DedicatedDeploymentTargetCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "dedicated", + "enterprise", + "local" + ], + "title": "Deployment target type", + "description": "The type of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The type of the deployment target." + ] + }, + "name": { + "type": "string", + "title": "Deployment target name", + "description": "The name of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The name of the deployment target." + ] + }, + "enforced_mounts": { + "type": "object", + "title": "Enforced Mounts", + "description": "Mounts which are always injected into pushed (e.g. enforce /var/log to be a local mount).", + "x-isDateTime": false, + "x-description": [ + "Mounts which are always injected into pushed (e.g. enforce /var/log to be a local mount)." + ] + } + }, + "required": [ + "type", + "name" + ], + "additionalProperties": false + }, + "DedicatedDeploymentTargetPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "dedicated", + "enterprise", + "local" + ], + "title": "Deployment target type", + "description": "The type of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The type of the deployment target." + ] + }, + "name": { + "type": "string", + "title": "Deployment target name", + "description": "The name of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The name of the deployment target." + ] + }, + "enforced_mounts": { + "type": "object", + "title": "Enforced Mounts", + "description": "Mounts which are always injected into pushed (e.g. enforce /var/log to be a local mount).", + "x-isDateTime": false, + "x-description": [ + "Mounts which are always injected into pushed (e.g. enforce /var/log to be a local mount)." + ] + } + }, + "required": [ + "type", + "name" + ], + "additionalProperties": false + }, + "Deployment": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Deployment Identifier", + "description": "The identifier of Deployment", + "x-isDateTime": false, + "x-description": [ + "The identifier of Deployment" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date of the deployment", + "x-isDateTime": true, + "x-description": [ + "The creation date of the deployment" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date of the deployment", + "x-isDateTime": true, + "x-description": [ + "The update date of the deployment" + ] + }, + "fingerprint": { + "type": "string", + "title": "Deployment fingerprint", + "description": "The fingerprint of the deployment", + "x-isDateTime": false, + "x-description": [ + "The fingerprint of the deployment" + ] + }, + "cluster_name": { + "type": "string", + "title": "Cluster name", + "description": "The name of the cluster", + "x-isDateTime": false, + "x-description": [ + "The name of the cluster" + ] + }, + "project_info": { + "type": "object", + "properties": { + "title": { + "type": "string", + "title": "Title", + "description": "" + }, + "name": { + "type": "string", + "title": "Name", + "description": "" + }, + "namespace": { + "type": "string", + "nullable": true, + "title": "Namespace", + "description": "" + }, + "organization": { + "type": "string", + "nullable": true, + "title": "Organization", + "description": "" + }, + "capabilities": { + "type": "object", + "title": "Capabilities", + "description": "" + }, + "settings": { + "type": "object", + "title": "Settings", + "description": "" + } + }, + "required": [ + "title", + "name", + "namespace", + "organization", + "capabilities", + "settings" + ], + "additionalProperties": false, + "title": "Project info", + "description": "The project information", + "x-isDateTime": false, + "x-description": [ + "The project information" + ] + }, + "environment_info": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Environment name", + "description": "The machine name of the environment", + "x-description": [ + "The machine name of the environment" + ] + }, + "status": { + "type": "string", + "title": "Environment status", + "description": "The enviroment status", + "x-description": [ + "The enviroment status" + ] + }, + "is_main": { + "type": "boolean", + "title": "Is main environment", + "description": "Is this environment the main environment", + "x-description": [ + "Is this environment the main environment" + ] + }, + "is_production": { + "type": "boolean", + "title": "Is production environment", + "description": "Is this environment a production environment", + "x-description": [ + "Is this environment a production environment" + ] + }, + "constraints": { + "type": "object", + "title": "Environment constraints", + "description": "Constraints of the environment's deployment", + "x-description": [ + "Constraints of the environment's deployment" + ] + }, + "reference": { + "type": "string", + "title": "Git reference", + "description": "The reference in Git for this environment", + "x-description": [ + "The reference in Git for this environment" + ] + }, + "machine_name": { + "type": "string", + "title": "Machine name", + "description": "The machine name of the environment", + "x-description": [ + "The machine name of the environment" + ] + }, + "environment_type": { + "type": "string", + "title": "Environment type", + "description": "The type of environment (Production, Staging or Development)", + "x-description": [ + "The type of environment (Production, Staging or Development)" + ] + }, + "links": { + "type": "object", + "title": "Links", + "description": "" + } + }, + "required": [ + "name", + "status", + "is_main", + "is_production", + "constraints", + "reference", + "machine_name", + "environment_type", + "links" + ], + "additionalProperties": false, + "title": "Environment info", + "description": "The environment information", + "x-isDateTime": false, + "x-description": [ + "The environment information" + ] + }, + "deployment_target": { + "type": "string", + "title": "Deployment target", + "description": "The deployment target", + "x-isDateTime": false, + "x-description": [ + "The deployment target" + ] + }, + "vpn": { + "type": "object", + "properties": { + "version": { + "type": "integer", + "enum": [ + 1, + 2 + ], + "title": "IKE Version", + "description": "The IKE version to use (1 or 2)", + "x-description": [ + "The IKE version to use (1 or 2)" + ] + }, + "aggressive": { + "type": "string", + "enum": [ + "no", + "yes" + ], + "title": "Aggressive Mode", + "description": "Whether to use IKEv1 Aggressive or Main Mode", + "x-description": [ + "Whether to use IKEv1 Aggressive or Main Mode" + ] + }, + "modeconfig": { + "type": "string", + "enum": [ + "pull", + "push" + ], + "title": "Mode Config", + "description": "Defines which mode is used to assign a virtual IP (must be the same on both sides)", + "x-description": [ + "Defines which mode is used to assign a virtual IP (must be the same on both sides)" + ] + }, + "authentication": { + "type": "string", + "title": "Authentication scheme", + "description": "The authentication scheme", + "x-description": [ + "The authentication scheme" + ] + }, + "gateway_ip": { + "type": "string", + "title": "Remote gateway IP", + "description": "" + }, + "identity": { + "type": "string", + "nullable": true, + "title": "Identity", + "description": "The identity of the ipsec participant", + "x-description": [ + "The identity of the ipsec participant" + ] + }, + "second_identity": { + "type": "string", + "nullable": true, + "title": "Second Identity", + "description": "The second identity of the ipsec participant", + "x-description": [ + "The second identity of the ipsec participant" + ] + }, + "remote_identity": { + "type": "string", + "nullable": true, + "title": "Remote Identity", + "description": "The identity of the remote ipsec participant", + "x-description": [ + "The identity of the remote ipsec participant" + ] + }, + "remote_subnets": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Remote Subnets", + "description": "Remote subnets (CIDR notation)", + "x-description": [ + "Remote subnets (CIDR notation)" + ] + }, + "ike": { + "type": "string", + "title": "IKE algorithms", + "description": "The IKE algorithms to negotiate for this VPN connection.", + "x-description": [ + "The IKE algorithms to negotiate for this VPN connection." + ] + }, + "esp": { + "type": "string", + "title": "ESP algorithms", + "description": "The ESP algorithms to negotiate for this VPN connection.", + "x-description": [ + "The ESP algorithms to negotiate for this VPN connection." + ] + }, + "ikelifetime": { + "type": "string", + "title": "IKE Lifetime", + "description": "The lifetime of the IKE exchange.", + "x-description": [ + "The lifetime of the IKE exchange." + ] + }, + "lifetime": { + "type": "string", + "title": "ESP Lifetime", + "description": "The lifetime of the ESP exchange.", + "x-description": [ + "The lifetime of the ESP exchange." + ] + }, + "margintime": { + "type": "string", + "title": "Margin Time", + "description": "The margin time for re-keying.", + "x-description": [ + "The margin time for re-keying." + ] + } + }, + "required": [ + "version", + "aggressive", + "modeconfig", + "authentication", + "gateway_ip", + "identity", + "second_identity", + "remote_identity", + "remote_subnets", + "ike", + "esp", + "ikelifetime", + "lifetime", + "margintime" + ], + "additionalProperties": false, + "nullable": true, + "title": "VPN configuration", + "description": "The configuration of the VPN", + "x-isDateTime": false, + "x-description": [ + "The configuration of the VPN" + ] + }, + "http_access": { + "type": "object", + "properties": { + "is_enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether http_access control is enabled", + "x-description": [ + "Whether http_access control is enabled" + ] + }, + "addresses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "permission": { + "type": "string", + "enum": [ + "allow", + "deny" + ], + "title": "Permission", + "description": "" + }, + "address": { + "type": "string", + "title": "Address", + "description": "IP address or CIDR" + } + }, + "required": [ + "permission", + "address" + ], + "additionalProperties": false + }, + "title": "Address grants", + "description": "" + }, + "basic_auth": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Basic auth grants", + "description": "" + } + }, + "required": [ + "is_enabled", + "addresses", + "basic_auth" + ], + "additionalProperties": false, + "title": "Http access permissions", + "description": "The permissions of the HTTP access", + "x-isDateTime": false, + "x-description": [ + "The permissions of the HTTP access" + ] + }, + "enable_smtp": { + "type": "boolean", + "title": "Enable SMTP", + "description": "Whether to configure SMTP for this environment", + "x-isDateTime": false, + "x-description": [ + "Whether to configure SMTP for this environment" + ] + }, + "restrict_robots": { + "type": "boolean", + "title": "Restrict robots", + "description": "Whether to restrict robots for this environment", + "x-isDateTime": false, + "x-description": [ + "Whether to restrict robots for this environment" + ] + }, + "variables": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Variable name", + "description": "Name of the variable" + }, + "value": { + "type": "string", + "title": "Variable value", + "description": "Value of the variable" + }, + "is_sensitive": { + "type": "boolean", + "title": "Is sensitive", + "description": "The variable is sensitive" + }, + "is_json": { + "type": "boolean", + "title": "Is JSON", + "description": "The variable is a JSON string" + }, + "visible_build": { + "type": "boolean", + "title": "Visible at build time", + "description": "The variable is visible during build" + }, + "visible_runtime": { + "type": "boolean", + "title": "Visible at runtime", + "description": "The variable is visible at runtime" + } + }, + "required": [ + "name", + "is_sensitive", + "is_json", + "visible_build", + "visible_runtime" + ], + "additionalProperties": false + }, + "title": "Environment variables", + "description": "The variables applying to this environment", + "x-isDateTime": false, + "x-description": [ + "The variables applying to this environment" + ] + }, + "access": { + "type": "array", + "items": { + "type": "object", + "properties": { + "entity_id": { + "type": "string", + "title": "Entity ID", + "description": "" + }, + "role": { + "type": "string", + "enum": [ + "admin", + "contributor", + "viewer" + ], + "title": "Role", + "description": "" + } + }, + "required": [ + "entity_id", + "role" + ], + "additionalProperties": false + }, + "title": "Access control", + "description": "Access control definition for this enviroment", + "x-isDateTime": false, + "x-description": [ + "Access control definition for this enviroment" + ] + }, + "subscription": { + "type": "object", + "properties": { + "license_uri": { + "type": "string", + "title": "Subscription URI", + "description": "URI of the subscription", + "x-description": [ + "URI of the subscription" + ] + }, + "plan": { + "type": "string", + "enum": [ + "2xlarge", + "2xlarge-high-memory", + "4xlarge", + "8xlarge", + "development", + "large", + "large-high-memory", + "medium", + "medium-high-memory", + "standard", + "standard-high-memory", + "xlarge", + "xlarge-high-memory" + ], + "title": "Plan level", + "description": "" + }, + "environments": { + "type": "integer", + "title": "Environments number", + "description": "Number of environments", + "x-description": [ + "Number of environments" + ] + }, + "storage": { + "type": "integer", + "title": "Storage", + "description": "Size of storage (in MB)", + "x-description": [ + "Size of storage (in MB)" + ] + }, + "included_users": { + "type": "integer", + "title": "Included users", + "description": "Number of users", + "x-description": [ + "Number of users" + ] + }, + "subscription_management_uri": { + "type": "string", + "title": "Subscription management URI", + "description": "URI for managing the subscription", + "x-description": [ + "URI for managing the subscription" + ] + }, + "restricted": { + "type": "boolean", + "title": "Is subscription attributes frozen", + "description": "True if subscription attributes, like number of users, are frozen", + "x-description": [ + "True if subscription attributes, like number of users, are frozen" + ] + }, + "suspended": { + "type": "boolean", + "title": "Is subscription suspended", + "description": "Whether or not the subscription is suspended", + "x-description": [ + "Whether or not the subscription is suspended" + ] + }, + "user_licenses": { + "type": "integer", + "title": "Current number of users", + "description": "Current number of users", + "x-description": [ + "Current number of users" + ] + }, + "resources": { + "type": "object", + "properties": { + "container_profiles": { + "type": "boolean", + "title": "Is Container profiles enabled", + "description": "Enable support for customizable container profiles.", + "x-description": [ + "Enable support for customizable container profiles." + ] + }, + "production": { + "type": "object", + "properties": { + "legacy_development": { + "type": "boolean", + "title": "Legacy development sizing", + "description": "Enable legacy development sizing for this environment type.", + "x-description": [ + "Enable legacy development sizing for this environment type." + ] + }, + "max_cpu": { + "type": "number", + "format": "float", + "nullable": true, + "title": "Maximum CPU units", + "description": "Maximum number of allocated CPU units.", + "x-description": [ + "Maximum number of allocated CPU units." + ] + }, + "max_memory": { + "type": "integer", + "nullable": true, + "title": "Maximum RAM", + "description": "Maximum amount of allocated RAM.", + "x-description": [ + "Maximum amount of allocated RAM." + ] + }, + "max_environments": { + "type": "integer", + "nullable": true, + "title": "Maximum environments", + "description": "Maximum number of environments", + "x-description": [ + "Maximum number of environments" + ] + } + }, + "required": [ + "legacy_development", + "max_cpu", + "max_memory", + "max_environments" + ], + "additionalProperties": false, + "title": "Production resources", + "description": "Resources for production environments", + "x-description": [ + "Resources for production environments" + ] + }, + "development": { + "type": "object", + "properties": { + "legacy_development": { + "type": "boolean", + "title": "Legacy development sizing", + "description": "Enable legacy development sizing for this environment type.", + "x-description": [ + "Enable legacy development sizing for this environment type." + ] + }, + "max_cpu": { + "type": "number", + "format": "float", + "nullable": true, + "title": "Maximum CPU units", + "description": "Maximum number of allocated CPU units.", + "x-description": [ + "Maximum number of allocated CPU units." + ] + }, + "max_memory": { + "type": "integer", + "nullable": true, + "title": "Maximum RAM", + "description": "Maximum amount of allocated RAM.", + "x-description": [ + "Maximum amount of allocated RAM." + ] + }, + "max_environments": { + "type": "integer", + "nullable": true, + "title": "Maximum environments", + "description": "Maximum number of environments", + "x-description": [ + "Maximum number of environments" + ] + } + }, + "required": [ + "legacy_development", + "max_cpu", + "max_memory", + "max_environments" + ], + "additionalProperties": false, + "title": "Development resources", + "description": "Resources for development environments", + "x-description": [ + "Resources for development environments" + ] + } + }, + "required": [ + "container_profiles", + "production", + "development" + ], + "additionalProperties": false, + "title": "Resources limits", + "description": "Resources limits", + "x-description": [ + "Resources limits" + ] + }, + "resource_validation_url": { + "type": "string", + "title": "Resource validation URL", + "description": "URL for resources validation", + "x-description": [ + "URL for resources validation" + ] + }, + "image_types": { + "type": "object", + "properties": { + "only": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Allowed image types", + "description": "Image types to be allowed use.", + "x-description": [ + "Image types to be allowed use." + ] + }, + "exclude": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Denied image types", + "description": "Image types to be denied use.", + "x-description": [ + "Image types to be denied use." + ] + } + }, + "additionalProperties": false, + "title": "Image type restrictions", + "description": "Restricted and denied image types", + "x-description": [ + "Restricted and denied image types" + ] + } + }, + "required": [ + "license_uri", + "storage", + "included_users", + "subscription_management_uri", + "restricted", + "suspended", + "user_licenses" + ], + "additionalProperties": false, + "title": "Subscription", + "description": "Subscription", + "x-isDateTime": false, + "x-description": [ + "Subscription" + ] + }, + "services": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Service type", + "description": "The service type." + }, + "size": { + "type": "string", + "enum": [ + "2XL", + "4XL", + "AUTO", + "L", + "M", + "S", + "XL" + ], + "title": "Service size", + "description": "The service size." + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "The size of the disk.", + "description": "" + }, + "access": { + "type": "object", + "title": "Access configuration", + "description": "The configuration of the service." + }, + "configuration": { + "type": "object", + "title": "Service configuration", + "description": "The configuration of the service." + }, + "relationships": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Service relationships", + "description": "The relationships of the service to other services." + }, + "firewall": { + "type": "object", + "properties": { + "outbound": { + "type": "array", + "items": { + "type": "object", + "properties": { + "protocol": { + "type": "string", + "enum": [ + "tcp" + ], + "title": "IP Protocol", + "description": "The IP protocol to apply the restriction on." + }, + "ips": { + "type": "array", + "items": { + "type": "string" + }, + "title": "IP Ranges", + "description": "The IP range in CIDR notation to apply the restriction on." + }, + "domains": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Domains", + "description": "Domains of the restriction." + }, + "ports": { + "type": "array", + "items": { + "type": "integer" + }, + "title": "Ports", + "description": "The port to apply the restriction on." + } + }, + "required": [ + "protocol", + "ips", + "domains", + "ports" + ], + "additionalProperties": false + }, + "title": "Outbound Firewall Restrictions", + "description": "Outbound firewall restrictions" + } + }, + "required": [ + "outbound" + ], + "additionalProperties": false, + "nullable": true, + "title": "Firewall", + "description": "" + }, + "resources": { + "type": "object", + "properties": { + "base_memory": { + "type": "integer", + "nullable": true, + "title": "Base memory", + "description": "The base memory for the container" + }, + "memory_ratio": { + "type": "integer", + "nullable": true, + "title": "Memory ratio", + "description": "The amount of memory to allocate per units of CPU" + }, + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "Selected size from container profile" + }, + "minimum": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "Cpu value" + }, + "memory": { + "type": "integer", + "title": "Memory", + "description": "Memory in MB" + }, + "cpu_type": { + "type": "string", + "enum": [ + "guaranteed", + "shared" + ], + "title": "Type", + "description": "resource type" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "Disk size in MB" + }, + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "The closest profile size that matches the resources" + } + }, + "required": [ + "cpu", + "memory", + "cpu_type", + "disk", + "profile_size" + ], + "additionalProperties": false, + "nullable": true, + "title": "Minimum resources", + "description": "The minimum resources for this service" + }, + "default": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "Cpu value" + }, + "memory": { + "type": "integer", + "title": "Memory", + "description": "Memory in MB" + }, + "cpu_type": { + "type": "string", + "enum": [ + "guaranteed", + "shared" + ], + "title": "Type", + "description": "resource type" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "Disk size in MB" + }, + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "The closest profile size that matches the resources" + } + }, + "required": [ + "cpu", + "memory", + "cpu_type", + "disk", + "profile_size" + ], + "additionalProperties": false, + "nullable": true, + "title": "Default resources", + "description": "The default resources for this service" + }, + "disk": { + "type": "object", + "properties": { + "temporary": { + "type": "integer", + "nullable": true, + "title": "Temporary", + "description": "" + }, + "instance": { + "type": "integer", + "nullable": true, + "title": "Instance", + "description": "" + }, + "storage": { + "type": "integer", + "nullable": true, + "title": "Storage", + "description": "" + } + }, + "required": [ + "temporary", + "instance", + "storage" + ], + "additionalProperties": false, + "nullable": true, + "title": "Disk resources", + "description": "The disks resources" + } + }, + "required": [ + "base_memory", + "memory_ratio", + "profile_size", + "minimum", + "default", + "disk" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "" + }, + "container_profile": { + "type": "string", + "nullable": true, + "title": "Container profile", + "description": "Selected container profile for the service" + }, + "endpoints": { + "type": "object", + "nullable": true, + "title": "Endpoints", + "description": "" + }, + "instance_count": { + "type": "integer", + "nullable": true, + "title": "Instance count", + "description": "Instance replication count of this service" + } + }, + "required": [ + "type", + "size", + "disk", + "access", + "configuration", + "relationships", + "firewall", + "resources", + "container_profile", + "endpoints", + "instance_count" + ], + "additionalProperties": false + }, + "title": "Services", + "description": "The services", + "x-isDateTime": false, + "x-description": [ + "The services" + ] + }, + "routes": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/components/schemas/ProxyRoute" + }, + { + "$ref": "#/components/schemas/RedirectRoute" + }, + { + "$ref": "#/components/schemas/UpstreamRoute" + } + ] + }, + "title": "Routes", + "description": "The routes", + "x-isDateTime": false, + "x-description": [ + "The routes" + ] + }, + "webapps": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "properties": { + "base_memory": { + "type": "integer", + "nullable": true, + "title": "Base memory", + "description": "The base memory for the container" + }, + "memory_ratio": { + "type": "integer", + "nullable": true, + "title": "Memory ratio", + "description": "The amount of memory to allocate per units of CPU" + }, + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "Selected size from container profile" + }, + "minimum": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "Cpu value" + }, + "memory": { + "type": "integer", + "title": "Memory", + "description": "Memory in MB" + }, + "cpu_type": { + "type": "string", + "enum": [ + "guaranteed", + "shared" + ], + "title": "Type", + "description": "resource type" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "Disk size in MB" + }, + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "The closest profile size that matches the resources" + } + }, + "required": [ + "cpu", + "memory", + "cpu_type", + "disk", + "profile_size" + ], + "additionalProperties": false, + "nullable": true, + "title": "Minimum resources", + "description": "The minimum resources for this service" + }, + "default": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "Cpu value" + }, + "memory": { + "type": "integer", + "title": "Memory", + "description": "Memory in MB" + }, + "cpu_type": { + "type": "string", + "enum": [ + "guaranteed", + "shared" + ], + "title": "Type", + "description": "resource type" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "Disk size in MB" + }, + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "The closest profile size that matches the resources" + } + }, + "required": [ + "cpu", + "memory", + "cpu_type", + "disk", + "profile_size" + ], + "additionalProperties": false, + "nullable": true, + "title": "Default resources", + "description": "The default resources for this service" + }, + "disk": { + "type": "object", + "properties": { + "temporary": { + "type": "integer", + "nullable": true, + "title": "Temporary", + "description": "" + }, + "instance": { + "type": "integer", + "nullable": true, + "title": "Instance", + "description": "" + }, + "storage": { + "type": "integer", + "nullable": true, + "title": "Storage", + "description": "" + } + }, + "required": [ + "temporary", + "instance", + "storage" + ], + "additionalProperties": false, + "nullable": true, + "title": "Disk resources", + "description": "The disks resources" + } + }, + "required": [ + "base_memory", + "memory_ratio", + "profile_size", + "minimum", + "default", + "disk" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "" + }, + "size": { + "type": "string", + "enum": [ + "2XL", + "4XL", + "AUTO", + "L", + "M", + "S", + "XL", + "XS" + ], + "title": "Container Size", + "description": "The container size for this application in production. Leave blank to allow it to be set dynamically." + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "The size of the disk." + }, + "access": { + "type": "object", + "additionalProperties": { + "type": "string", + "enum": [ + "admin", + "contributor", + "viewer" + ] + }, + "title": "Access Information", + "description": "Access information, a mapping between access type and roles." + }, + "relationships": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "service": { + "type": "string", + "nullable": true, + "title": "Service Name", + "description": "The name of the service." + }, + "endpoint": { + "type": "string", + "nullable": true, + "title": "Endpoint Name", + "description": "The name of the endpoint on the service." + } + }, + "required": [ + "service", + "endpoint" + ], + "additionalProperties": false, + "nullable": true + }, + "title": "Service Relationships", + "description": "The relationships of the application to defined services." + }, + "additional_hosts": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Additional hosts", + "description": "A mapping of hostname to ip address to be added to the container's hosts file" + }, + "mounts": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "source": { + "type": "string", + "enum": [ + "instance", + "local", + "service", + "storage", + "temporary", + "tmp" + ], + "title": "Mount type", + "description": "The type of mount that will provide the data." + }, + "source_path": { + "type": "string", + "title": "Source Path", + "description": "The path to be mounted, relative to the root directory of the volume that's being mounted from." + }, + "service": { + "type": "string", + "nullable": true, + "title": "Service Name", + "description": "The name of the service that the volume will be mounted from. Must be a service in `services.yaml` of type `network-storage`." + } + }, + "required": [ + "source", + "source_path" + ], + "additionalProperties": false + }, + "title": "Mounts", + "description": "Filesystem mounts of this application. If not specified the application will have no writeable disk space." + }, + "timezone": { + "type": "string", + "nullable": true, + "title": "Timezone", + "description": "The timezone of the application. This primarily affects the timezone in which cron tasks will run. It will not affect the application itself. Defaults to UTC if not specified." + }, + "variables": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": {} + }, + "title": "Environment Variables", + "description": "Variables provide environment-sensitive information to control how your application behaves. To set a Unix environment variable, specify a key of `env:`, and then each sub-item of that is a key/value pair that will be injected into the environment." + }, + "firewall": { + "type": "object", + "properties": { + "outbound": { + "type": "array", + "items": { + "type": "object", + "properties": { + "protocol": { + "type": "string", + "enum": [ + "tcp" + ], + "title": "IP Protocol", + "description": "The IP protocol to apply the restriction on." + }, + "ips": { + "type": "array", + "items": { + "type": "string" + }, + "title": "IP Ranges", + "description": "The IP range in CIDR notation to apply the restriction on." + }, + "domains": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Domains", + "description": "Domains of the restriction." + }, + "ports": { + "type": "array", + "items": { + "type": "integer" + }, + "title": "Ports", + "description": "The port to apply the restriction on." + } + }, + "required": [ + "protocol", + "ips", + "domains", + "ports" + ], + "additionalProperties": false + }, + "title": "Outbound Firewall Restrictions", + "description": "Outbound firewall restrictions" + } + }, + "required": [ + "outbound" + ], + "additionalProperties": false, + "nullable": true, + "title": "Firewall", + "description": "" + }, + "container_profile": { + "type": "string", + "nullable": true, + "title": "Container Profile", + "description": "Selected container profile for the application" + }, + "operations": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "commands": { + "type": "object", + "properties": { + "start": { + "type": "string", + "title": "Start Command", + "description": "The command used to start the operation." + }, + "stop": { + "type": "string", + "nullable": true, + "title": "Stop Command", + "description": "The command used to stop the operation." + } + }, + "required": [ + "start" + ], + "additionalProperties": false, + "title": "Commands", + "description": "The commands definition." + }, + "timeout": { + "type": "integer", + "nullable": true, + "title": "Timeout", + "description": "The maximum timeout in seconds after which the operation will be forcefully killed." + }, + "role": { + "type": "string", + "enum": [ + "admin", + "contributor", + "viewer" + ], + "title": "Role", + "description": "The minimum role necessary to trigger this operation." + } + }, + "required": [ + "commands", + "timeout", + "role" + ], + "additionalProperties": false + }, + "title": "Operations", + "description": "Operations that can be triggered on this application" + }, + "name": { + "type": "string", + "title": "Application Name", + "description": "The name of the application. Must be unique within a project." + }, + "type": { + "type": "string", + "title": "Type", + "description": "The base runtime and version to use for this worker." + }, + "preflight": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Preflight Security Blocks", + "description": "Whether the preflight security blocks are enabled." + }, + "ignored_rules": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Ignored Rules", + "description": "Specific rules to ignore during preflight security checks. See the documentation for options." + } + }, + "required": [ + "enabled", + "ignored_rules" + ], + "additionalProperties": false, + "title": "Preflight Checks", + "description": "Configuration for pre-flight checks." + }, + "tree_id": { + "type": "string", + "title": "Source Tree ID", + "description": "The identifier of the source tree of the application" + }, + "app_dir": { + "type": "string", + "title": "Application Directory", + "description": "The path of the application in the container" + }, + "endpoints": { + "type": "object", + "nullable": true, + "title": "Endpoints", + "description": "" + }, + "runtime": { + "type": "object", + "title": "Runtime Configuration", + "description": "Runtime-specific configuration." + }, + "web": { + "type": "object", + "properties": { + "locations": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "root": { + "type": "string", + "nullable": true, + "title": "Document Root", + "description": "The folder from which to serve static assets for this location relative to the application root." + }, + "expires": { + "type": "string", + "title": "Expires", + "description": "Amount of time to cache static assets." + }, + "passthru": { + "type": "string", + "title": "Passthru", + "description": "Whether to forward disallowed and missing resources from this location to the application. On PHP, set to the PHP front controller script, as a URL fragment. Otherwise set to `true`/`false`." + }, + "scripts": { + "type": "boolean", + "title": "Scripts", + "description": "Whether to execute scripts in this location (for script based runtimes)." + }, + "index": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "title": "Index Files", + "description": "Files to look for to serve directories." + }, + "allow": { + "type": "boolean", + "title": "Allow access", + "description": "Whether to allow access to this location by default." + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Headers", + "description": "A set of header fields set to the HTTP response. Applies only to static files, not responses from the application." + }, + "rules": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "expires": { + "type": "string", + "nullable": true, + "title": "Expires", + "description": "Amount of time to cache static assets." + }, + "passthru": { + "type": "string", + "title": "Passthru", + "description": "Whether to forward disallowed and missing resources from this location to the application. On PHP, set to the PHP front controller script, as a URL fragment. Otherwise set to `true`/`false`." + }, + "scripts": { + "type": "boolean", + "title": "Scripts", + "description": "Whether to execute scripts in this location (for script based runtimes)." + }, + "allow": { + "type": "boolean", + "title": "Allow access", + "description": "Whether to allow access to this location by default." + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Headers", + "description": "A set of header fields set to the HTTP response. Replaces headers set on the location block." + } + }, + "additionalProperties": false + }, + "title": "Specific overrides", + "description": "Specific overrides." + }, + "request_buffering": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Request Buffering", + "description": "Enable request buffering." + }, + "max_request_size": { + "type": "string", + "nullable": true, + "title": "Maximum request size", + "description": "The maximum size request that can be buffered. Supports K, M, and G suffixes." + } + }, + "required": [ + "enabled", + "max_request_size" + ], + "additionalProperties": false, + "title": "Request Buffering", + "description": "Configuration for supporting request buffering." + } + }, + "required": [ + "root", + "expires", + "passthru", + "scripts", + "allow", + "headers", + "rules" + ], + "additionalProperties": false + }, + "title": "Web Locations", + "description": "The specification of the web locations served by this application." + }, + "commands": { + "type": "object", + "properties": { + "pre_start": { + "type": "string", + "nullable": true, + "title": "Pre-start Command", + "description": "A command executed before the application is started" + }, + "start": { + "type": "string", + "nullable": true, + "title": "Start Command", + "description": "The command used to start the application. It will be restarted if it terminates. Do not use on PHP unless using a custom persistent process like React PHP." + }, + "post_start": { + "type": "string", + "nullable": true, + "title": "Post-start Command", + "description": "A command executed after the application is started" + } + }, + "additionalProperties": false, + "title": "Commands", + "description": "Commands to manage the application's lifecycle." + }, + "upstream": { + "type": "object", + "properties": { + "socket_family": { + "type": "string", + "enum": [ + "tcp", + "unix" + ], + "title": "Socket Family", + "description": "If `tcp`, check the PORT environment variable on application startup. If `unix`, check SOCKET." + }, + "protocol": { + "type": "string", + "enum": [ + "fastcgi", + "http" + ], + "nullable": true, + "title": "Protocol", + "description": "" + } + }, + "required": [ + "socket_family", + "protocol" + ], + "additionalProperties": false, + "title": "Upstream Configuration", + "description": "Configuration on how the web server communicates with the application." + }, + "document_root": { + "type": "string", + "nullable": true, + "title": "Document Root", + "description": "The document root of this application, relative to its root." + }, + "passthru": { + "type": "string", + "nullable": true, + "title": "Passthru", + "description": "The URL to use as a passthru if a file doesn't match the whitelist." + }, + "index_files": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "title": "Index Files", + "description": "Files to look for to serve directories." + }, + "whitelist": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "title": "Whitelisted entries", + "description": "Whitelisted entries." + }, + "blacklist": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "title": "Blacklisted entries", + "description": "Blacklisted entries." + }, + "expires": { + "type": "string", + "nullable": true, + "title": "Expires", + "description": "Amount of time to cache static assets." + }, + "move_to_root": { + "type": "boolean", + "title": "Move to root", + "description": "Whether to move the whole root of the app to the document root." + } + }, + "required": [ + "locations", + "move_to_root" + ], + "additionalProperties": false, + "title": "Web Configuration", + "description": "Configuration for accessing this application via HTTP." + }, + "hooks": { + "type": "object", + "properties": { + "build": { + "type": "string", + "nullable": true, + "title": "Build Hook", + "description": "Hook executed after the build process." + }, + "deploy": { + "type": "string", + "nullable": true, + "title": "Deploy Hook", + "description": "Hook executed after the deployment of new code." + }, + "post_deploy": { + "type": "string", + "nullable": true, + "title": "Post-deploy Hook", + "description": "Hook executed after an environment is fully deployed." + } + }, + "required": [ + "build", + "deploy", + "post_deploy" + ], + "additionalProperties": false, + "title": "Hooks", + "description": "Hooks executed at various point in the lifecycle of the application." + }, + "crons": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "spec": { + "type": "string", + "title": "Specification", + "description": "The cron schedule specification." + }, + "commands": { + "type": "object", + "properties": { + "start": { + "type": "string", + "title": "Start Command", + "description": "The command used to start the operation." + }, + "stop": { + "type": "string", + "nullable": true, + "title": "Stop Command", + "description": "The command used to stop the operation." + } + }, + "required": [ + "start" + ], + "additionalProperties": false, + "title": "Commands", + "description": "The commands definition." + }, + "shutdown_timeout": { + "type": "integer", + "nullable": true, + "title": "Shutdown Timeout", + "description": "The timeout in seconds after which the cron job will be forcefully killed." + }, + "timeout": { + "type": "integer", + "title": "Timeout", + "description": "The maximum timeout in seconds after which the cron job will be forcefully killed." + }, + "cmd": { + "type": "string", + "title": "Command", + "description": "The command to execute." + } + }, + "required": [ + "spec", + "commands", + "timeout" + ], + "additionalProperties": false + }, + "title": "Crons", + "description": "Scheduled cron tasks executed by this application." + }, + "source": { + "type": "object", + "properties": { + "root": { + "type": "string", + "nullable": true, + "title": "Application Source Root", + "description": "The root of the application relative to the repository root." + }, + "operations": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "command": { + "type": "string", + "nullable": true, + "title": "Update Command", + "description": "The command to use to update this application." + } + }, + "required": [ + "command" + ], + "additionalProperties": false + }, + "title": "Source Operations", + "description": "Operations that can be applied to the source code." + } + }, + "required": [ + "root", + "operations" + ], + "additionalProperties": false, + "title": "Source Code Configuration", + "description": "Configuration related to the source code of the application." + }, + "build": { + "type": "object", + "properties": { + "flavor": { + "type": "string", + "nullable": true, + "title": "Build Flavor", + "description": "The pre-set build tasks to use for this application." + }, + "caches": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "directory": { + "type": "string", + "nullable": true, + "title": "Cache Directory", + "description": "The directory, relative to the application root, that should be cached." + }, + "watch": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Watch Files", + "description": "The file or files whose hashed contents should be considered part of the cache key." + }, + "allow_stale": { + "type": "boolean", + "title": "Allow Stale Cache", + "description": "If true, on a cache miss the last cache version will be used and can be updated in place." + }, + "share_between_apps": { + "type": "boolean", + "title": "Share Between Applications", + "description": "Whether multiple applications in the project should share cached directories." + } + }, + "required": [ + "directory", + "watch", + "allow_stale", + "share_between_apps" + ], + "additionalProperties": false + }, + "title": "Build Caches", + "description": "The configuration of paths managed by the build cache." + } + }, + "required": [ + "flavor", + "caches" + ], + "additionalProperties": false, + "title": "Build Configuration", + "description": "The build configuration of the application." + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "type": "object" + }, + "title": "Dependencies", + "description": "External global dependencies of this application. They will be downloaded by the language's package manager." + }, + "stack": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "title": "Composable images", + "description": "" + }, + "is_across_submodule": { + "type": "boolean", + "title": "Is Across Submodule", + "description": "Is this application coming from a submodule" + }, + "instance_count": { + "type": "integer", + "nullable": true, + "title": "Instance replication count", + "description": "Instance replication count of this application" + }, + "config_id": { + "type": "string", + "title": "Config Id", + "description": "" + }, + "slug_id": { + "type": "string", + "title": "Artifact Identifier", + "description": "The identifier of the built artifact of the application" + } + }, + "required": [ + "resources", + "size", + "disk", + "access", + "relationships", + "additional_hosts", + "mounts", + "timezone", + "variables", + "firewall", + "container_profile", + "operations", + "name", + "type", + "preflight", + "tree_id", + "app_dir", + "endpoints", + "runtime", + "web", + "hooks", + "crons", + "source", + "build", + "dependencies", + "stack", + "is_across_submodule", + "instance_count", + "config_id", + "slug_id" + ], + "additionalProperties": false + }, + "title": "Web applications", + "description": "The Web applications", + "x-isDateTime": false, + "x-description": [ + "The Web applications" + ] + }, + "workers": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "properties": { + "base_memory": { + "type": "integer", + "nullable": true, + "title": "Base memory", + "description": "The base memory for the container" + }, + "memory_ratio": { + "type": "integer", + "nullable": true, + "title": "Memory ratio", + "description": "The amount of memory to allocate per units of CPU" + }, + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "Selected size from container profile" + }, + "minimum": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "Cpu value" + }, + "memory": { + "type": "integer", + "title": "Memory", + "description": "Memory in MB" + }, + "cpu_type": { + "type": "string", + "enum": [ + "guaranteed", + "shared" + ], + "title": "Type", + "description": "resource type" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "Disk size in MB" + }, + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "The closest profile size that matches the resources" + } + }, + "required": [ + "cpu", + "memory", + "cpu_type", + "disk", + "profile_size" + ], + "additionalProperties": false, + "nullable": true, + "title": "Minimum resources", + "description": "The minimum resources for this service" + }, + "default": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "Cpu value" + }, + "memory": { + "type": "integer", + "title": "Memory", + "description": "Memory in MB" + }, + "cpu_type": { + "type": "string", + "enum": [ + "guaranteed", + "shared" + ], + "title": "Type", + "description": "resource type" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "Disk size in MB" + }, + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "The closest profile size that matches the resources" + } + }, + "required": [ + "cpu", + "memory", + "cpu_type", + "disk", + "profile_size" + ], + "additionalProperties": false, + "nullable": true, + "title": "Default resources", + "description": "The default resources for this service" + }, + "disk": { + "type": "object", + "properties": { + "temporary": { + "type": "integer", + "nullable": true, + "title": "Temporary", + "description": "" + }, + "instance": { + "type": "integer", + "nullable": true, + "title": "Instance", + "description": "" + }, + "storage": { + "type": "integer", + "nullable": true, + "title": "Storage", + "description": "" + } + }, + "required": [ + "temporary", + "instance", + "storage" + ], + "additionalProperties": false, + "nullable": true, + "title": "Disk resources", + "description": "The disks resources" + } + }, + "required": [ + "base_memory", + "memory_ratio", + "profile_size", + "minimum", + "default", + "disk" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "" + }, + "size": { + "type": "string", + "enum": [ + "2XL", + "4XL", + "AUTO", + "L", + "M", + "S", + "XL", + "XS" + ], + "title": "Container Size", + "description": "The container size for this application in production. Leave blank to allow it to be set dynamically." + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "The writeable disk size to reserve on this application container." + }, + "access": { + "type": "object", + "additionalProperties": { + "type": "string", + "enum": [ + "admin", + "contributor", + "viewer" + ] + }, + "title": "Access Information", + "description": "Access information, a mapping between access type and roles." + }, + "relationships": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "service": { + "type": "string", + "nullable": true, + "title": "Service Name", + "description": "The name of the service." + }, + "endpoint": { + "type": "string", + "nullable": true, + "title": "Endpoint Name", + "description": "The name of the endpoint on the service." + } + }, + "required": [ + "service", + "endpoint" + ], + "additionalProperties": false, + "nullable": true + }, + "title": "Service Relationships", + "description": "The relationships of the application to defined services." + }, + "additional_hosts": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Additional hosts", + "description": "A mapping of hostname to ip address to be added to the container's hosts file" + }, + "mounts": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "source": { + "type": "string", + "enum": [ + "instance", + "local", + "service", + "storage", + "temporary", + "tmp" + ], + "title": "Mount type", + "description": "The type of mount that will provide the data." + }, + "source_path": { + "type": "string", + "title": "Source Path", + "description": "The path to be mounted, relative to the root directory of the volume that's being mounted from." + }, + "service": { + "type": "string", + "nullable": true, + "title": "Service Name", + "description": "The name of the service that the volume will be mounted from. Must be a service in `services.yaml` of type `network-storage`." + } + }, + "required": [ + "source", + "source_path" + ], + "additionalProperties": false + }, + "title": "Mounts", + "description": "Filesystem mounts of this application. If not specified the application will have no writeable disk space." + }, + "timezone": { + "type": "string", + "nullable": true, + "title": "Timezone", + "description": "The timezone of the application. This primarily affects the timezone in which cron tasks will run. It will not affect the application itself. Defaults to UTC if not specified." + }, + "variables": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": {} + }, + "title": "Environment Variables", + "description": "Variables provide environment-sensitive information to control how your application behaves. To set a Unix environment variable, specify a key of `env:`, and then each sub-item of that is a key/value pair that will be injected into the environment." + }, + "firewall": { + "type": "object", + "properties": { + "outbound": { + "type": "array", + "items": { + "type": "object", + "properties": { + "protocol": { + "type": "string", + "enum": [ + "tcp" + ], + "title": "IP Protocol", + "description": "The IP protocol to apply the restriction on." + }, + "ips": { + "type": "array", + "items": { + "type": "string" + }, + "title": "IP Ranges", + "description": "The IP range in CIDR notation to apply the restriction on." + }, + "domains": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Domains", + "description": "Domains of the restriction." + }, + "ports": { + "type": "array", + "items": { + "type": "integer" + }, + "title": "Ports", + "description": "The port to apply the restriction on." + } + }, + "required": [ + "protocol", + "ips", + "domains", + "ports" + ], + "additionalProperties": false + }, + "title": "Outbound Firewall Restrictions", + "description": "Outbound firewall restrictions" + } + }, + "required": [ + "outbound" + ], + "additionalProperties": false, + "nullable": true, + "title": "Firewall", + "description": "" + }, + "container_profile": { + "type": "string", + "nullable": true, + "title": "Container Profile", + "description": "Selected container profile for the application" + }, + "operations": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "commands": { + "type": "object", + "properties": { + "start": { + "type": "string", + "title": "Start Command", + "description": "The command used to start the operation." + }, + "stop": { + "type": "string", + "nullable": true, + "title": "Stop Command", + "description": "The command used to stop the operation." + } + }, + "required": [ + "start" + ], + "additionalProperties": false, + "title": "Commands", + "description": "The commands definition." + }, + "timeout": { + "type": "integer", + "nullable": true, + "title": "Timeout", + "description": "The maximum timeout in seconds after which the operation will be forcefully killed." + }, + "role": { + "type": "string", + "enum": [ + "admin", + "contributor", + "viewer" + ], + "title": "Role", + "description": "The minimum role necessary to trigger this operation." + } + }, + "required": [ + "commands", + "timeout", + "role" + ], + "additionalProperties": false + }, + "title": "Operations", + "description": "Operations that can be triggered on this application" + }, + "name": { + "type": "string", + "title": "Worker Name", + "description": "The name of the worker." + }, + "type": { + "type": "string", + "title": "Type", + "description": "The base runtime and version to use for this worker." + }, + "preflight": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Preflight Security Blocks", + "description": "Whether the preflight security blocks are enabled." + }, + "ignored_rules": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Ignored Rules", + "description": "Specific rules to ignore during preflight security checks. See the documentation for options." + } + }, + "required": [ + "enabled", + "ignored_rules" + ], + "additionalProperties": false, + "title": "Preflight Checks", + "description": "Configuration for pre-flight checks." + }, + "tree_id": { + "type": "string", + "title": "Source Tree ID", + "description": "The identifier of the source tree of the application" + }, + "app_dir": { + "type": "string", + "title": "Application Directory", + "description": "The path of the application in the container" + }, + "endpoints": { + "type": "object", + "nullable": true, + "title": "Endpoints", + "description": "" + }, + "runtime": { + "type": "object", + "title": "Runtime Configuration", + "description": "Runtime-specific configuration." + }, + "worker": { + "type": "object", + "properties": { + "commands": { + "type": "object", + "properties": { + "pre_start": { + "type": "string", + "nullable": true, + "title": "Pre-start Command", + "description": "A command executed before the worker is started" + }, + "start": { + "type": "string", + "title": "Start Command", + "description": "The command used to start the worker." + }, + "post_start": { + "type": "string", + "nullable": true, + "title": "Post-start Command", + "description": "A command executed after the worker is started" + } + }, + "required": [ + "start" + ], + "additionalProperties": false, + "title": "Commands", + "description": "The commands to manage the worker." + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk Size", + "description": "The writeable disk size to reserve on this application container." + } + }, + "required": [ + "commands" + ], + "additionalProperties": false, + "title": "Worker Configuration", + "description": "Configuration of a worker container instance." + }, + "app": { + "type": "string", + "title": "App", + "description": "" + }, + "stack": { + "type": "array", + "items": { + "type": "object" + }, + "nullable": true, + "title": "Composable images", + "description": "" + }, + "instance_count": { + "type": "integer", + "nullable": true, + "title": "Instance replication count", + "description": "Instance replication count of this worker" + }, + "slug_id": { + "type": "string", + "title": "Artifact Identifier", + "description": "The identifier of the built artifact of the application" + } + }, + "required": [ + "resources", + "size", + "disk", + "access", + "relationships", + "additional_hosts", + "mounts", + "timezone", + "variables", + "firewall", + "container_profile", + "operations", + "name", + "type", + "preflight", + "tree_id", + "app_dir", + "endpoints", + "runtime", + "worker", + "app", + "stack", + "instance_count", + "slug_id" + ], + "additionalProperties": false + }, + "title": "Workers", + "description": "The workers", + "x-isDateTime": false, + "x-description": [ + "The workers" + ] + }, + "container_profiles": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "Cpu value" + }, + "memory": { + "type": "integer", + "title": "Memory", + "description": "Memory in MB" + }, + "cpu_type": { + "type": "string", + "enum": [ + "guaranteed", + "shared" + ], + "title": "Type", + "description": "resource type" + } + }, + "required": [ + "cpu", + "memory", + "cpu_type" + ], + "additionalProperties": false + } + }, + "title": "Container profiles", + "description": "The profiles of the containers", + "x-isDateTime": false, + "x-description": [ + "The profiles of the containers" + ] + } + }, + "required": [ + "id", + "cluster_name", + "project_info", + "environment_info", + "deployment_target", + "vpn", + "http_access", + "enable_smtp", + "restrict_robots", + "variables", + "access", + "subscription", + "services", + "routes", + "webapps", + "workers", + "container_profiles" + ], + "additionalProperties": false + }, + "DeploymentCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Deployment" + } + }, + "DeploymentTarget": { + "oneOf": [ + { + "$ref": "#/components/schemas/DedicatedDeploymentTarget" + }, + { + "$ref": "#/components/schemas/EnterpriseDeploymentTarget" + }, + { + "$ref": "#/components/schemas/FoundationDeploymentTarget" + } + ] + }, + "DeploymentTargetCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DeploymentTarget" + } + }, + "DeploymentTargetCreateInput": { + "oneOf": [ + { + "$ref": "#/components/schemas/DedicatedDeploymentTargetCreateInput" + }, + { + "$ref": "#/components/schemas/EnterpriseDeploymentTargetCreateInput" + }, + { + "$ref": "#/components/schemas/FoundationDeploymentTargetCreateInput" + } + ] + }, + "DeploymentTargetPatch": { + "oneOf": [ + { + "$ref": "#/components/schemas/DedicatedDeploymentTargetPatch" + }, + { + "$ref": "#/components/schemas/EnterpriseDeploymentTargetPatch" + }, + { + "$ref": "#/components/schemas/FoundationDeploymentTargetPatch" + } + ] + }, + "Domain": { + "oneOf": [ + { + "$ref": "#/components/schemas/ProdDomainStorage" + }, + { + "$ref": "#/components/schemas/ReplacementDomainStorage" + } + ] + }, + "DomainCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Domain" + } + }, + "DomainCreateInput": { + "oneOf": [ + { + "$ref": "#/components/schemas/ProdDomainStorageCreateInput" + }, + { + "$ref": "#/components/schemas/ReplacementDomainStorageCreateInput" + } + ] + }, + "DomainPatch": { + "oneOf": [ + { + "$ref": "#/components/schemas/ProdDomainStoragePatch" + }, + { + "$ref": "#/components/schemas/ReplacementDomainStoragePatch" + } + ] + }, + "EmailIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "EmailIntegration Identifier", + "description": "The identifier of EmailIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of EmailIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "from_address": { + "type": "string", + "nullable": true, + "title": "From Address", + "description": "The email address to use", + "x-isDateTime": false, + "x-description": [ + "The email address to use" + ] + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Recipients", + "description": "Recipients of the email", + "x-isDateTime": false, + "x-description": [ + "Recipients of the email" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "from_address", + "recipients" + ], + "additionalProperties": false + }, + "EmailIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "from_address": { + "type": "string", + "nullable": true, + "title": "From Address", + "description": "The email address to use", + "x-isDateTime": false, + "x-description": [ + "The email address to use" + ] + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Recipients", + "description": "Recipients of the email", + "x-isDateTime": false, + "x-description": [ + "Recipients of the email" + ] + } + }, + "required": [ + "type", + "recipients" + ], + "additionalProperties": false + }, + "EmailIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "from_address": { + "type": "string", + "nullable": true, + "title": "From Address", + "description": "The email address to use", + "x-isDateTime": false, + "x-description": [ + "The email address to use" + ] + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Recipients", + "description": "Recipients of the email", + "x-isDateTime": false, + "x-description": [ + "Recipients of the email" + ] + } + }, + "required": [ + "type", + "recipients" + ], + "additionalProperties": false + }, + "EnterpriseDeploymentTarget": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "EnterpriseDeploymentTarget Identifier", + "description": "The identifier of EnterpriseDeploymentTarget", + "x-isDateTime": false, + "x-description": [ + "The identifier of EnterpriseDeploymentTarget" + ] + }, + "type": { + "type": "string", + "enum": [ + "dedicated", + "enterprise", + "local" + ], + "title": "Deployment target type", + "description": "The type of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The type of the deployment target." + ] + }, + "name": { + "type": "string", + "title": "Deployment target name", + "description": "The name of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The name of the deployment target." + ] + }, + "deploy_host": { + "type": "string", + "nullable": true, + "title": "Deploy Host", + "description": "The host to deploy to.", + "x-isDateTime": false, + "x-description": [ + "The host to deploy to." + ] + }, + "docroots": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "active_docroot": { + "type": "string", + "nullable": true, + "title": "Active docroot", + "description": "The enterprise docroot, that is associated with this application/cluster." + }, + "docroot_versions": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "title": "Docroot versions", + "description": "Versions of the enterprise docroot. When a new environment version is created the active_docroot is updated from these values." + } + }, + "required": [ + "active_docroot", + "docroot_versions" + ], + "additionalProperties": false + }, + "title": "Docroots", + "description": "Mapping of clusters to Enterprise applications", + "x-isDateTime": false, + "x-description": [ + "Mapping of clusters to Enterprise applications" + ] + }, + "site_urls": { + "type": "object", + "title": "Site URLs", + "description": "", + "x-isDateTime": false + }, + "ssh_hosts": { + "type": "array", + "items": { + "type": "string" + }, + "title": "SSH Hosts", + "description": "List of SSH Hosts.", + "x-isDateTime": false, + "x-description": [ + "List of SSH Hosts." + ] + }, + "maintenance_mode": { + "type": "boolean", + "title": "Maintenance Mode", + "description": "Whether to perform deployments or not", + "x-isDateTime": false, + "x-description": [ + "Whether to perform deployments or not" + ] + }, + "enterprise_environments_mapping": { + "type": "object", + "title": "Enterprise Environments Mapping", + "description": "Mapping of clusters to Enterprise applications", + "deprecated": true, + "x-stability": "DEPRECATED", + "x-isDateTime": false, + "x-description": [ + "Mapping of clusters to Enterprise applications" + ] + } + }, + "required": [ + "type", + "name", + "deploy_host", + "docroots", + "site_urls", + "ssh_hosts", + "maintenance_mode" + ], + "additionalProperties": false + }, + "EnterpriseDeploymentTargetCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "dedicated", + "enterprise", + "local" + ], + "title": "Deployment target type", + "description": "The type of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The type of the deployment target." + ] + }, + "name": { + "type": "string", + "title": "Deployment target name", + "description": "The name of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The name of the deployment target." + ] + }, + "site_urls": { + "type": "object", + "title": "Site URLs", + "description": "", + "x-isDateTime": false + }, + "ssh_hosts": { + "type": "array", + "items": { + "type": "string" + }, + "title": "SSH Hosts", + "description": "List of SSH Hosts.", + "x-isDateTime": false, + "x-description": [ + "List of SSH Hosts." + ] + }, + "enterprise_environments_mapping": { + "type": "object", + "title": "Enterprise Environments Mapping", + "description": "Mapping of clusters to Enterprise applications", + "deprecated": true, + "x-stability": "DEPRECATED", + "x-isDateTime": false, + "x-description": [ + "Mapping of clusters to Enterprise applications" + ] + } + }, + "required": [ + "type", + "name" + ], + "additionalProperties": false + }, + "EnterpriseDeploymentTargetPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "dedicated", + "enterprise", + "local" + ], + "title": "Deployment target type", + "description": "The type of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The type of the deployment target." + ] + }, + "name": { + "type": "string", + "title": "Deployment target name", + "description": "The name of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The name of the deployment target." + ] + }, + "site_urls": { + "type": "object", + "title": "Site URLs", + "description": "", + "x-isDateTime": false + }, + "ssh_hosts": { + "type": "array", + "items": { + "type": "string" + }, + "title": "SSH Hosts", + "description": "List of SSH Hosts.", + "x-isDateTime": false, + "x-description": [ + "List of SSH Hosts." + ] + }, + "enterprise_environments_mapping": { + "type": "object", + "title": "Enterprise Environments Mapping", + "description": "Mapping of clusters to Enterprise applications", + "deprecated": true, + "x-stability": "DEPRECATED", + "x-isDateTime": false, + "x-description": [ + "Mapping of clusters to Enterprise applications" + ] + } + }, + "required": [ + "type", + "name" + ], + "additionalProperties": false + }, + "Environment": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Environment Identifier", + "description": "The identifier of Environment", + "x-isDateTime": false, + "x-description": [ + "The identifier of Environment" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "name": { + "type": "string", + "title": "Name", + "description": "The name of the environment", + "x-isDateTime": false, + "x-description": [ + "The name of the environment" + ] + }, + "machine_name": { + "type": "string", + "title": "Machine name", + "description": "The machine name for the environment", + "x-isDateTime": false, + "x-description": [ + "The machine name for the environment" + ] + }, + "title": { + "type": "string", + "title": "Title", + "description": "The title of the environment", + "x-isDateTime": false, + "x-description": [ + "The title of the environment" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "type": { + "type": "string", + "enum": [ + "development", + "production", + "staging" + ], + "title": "Type", + "description": "The type of environment (`production`, `staging` or `development`), if not provided, a default will be calculated", + "x-isDateTime": false, + "x-description": [ + "The type of environment (`production`, `staging` or `development`), if not provided, a default will be calculated" + ] + }, + "parent": { + "type": "string", + "nullable": true, + "title": "Parent environment", + "description": "The name of the parent environment", + "x-isDateTime": false, + "x-description": [ + "The name of the parent environment" + ] + }, + "default_domain": { + "type": "string", + "nullable": true, + "title": "Default domain", + "description": "The default domain", + "x-isDateTime": false, + "x-description": [ + "The default domain" + ] + }, + "has_domains": { + "type": "boolean", + "title": "Has domains", + "description": "Whether the environment has domains", + "x-isDateTime": false, + "x-description": [ + "Whether the environment has domains" + ] + }, + "clone_parent_on_create": { + "type": "boolean", + "title": "Clone parent on create", + "description": "Clone data when creating that environment", + "x-isDateTime": false, + "x-description": [ + "Clone data when creating that environment" + ] + }, + "deployment_target": { + "type": "string", + "nullable": true, + "title": "Deployment target", + "description": "Deployment target of the environment", + "x-isDateTime": false, + "x-description": [ + "Deployment target of the environment" + ] + }, + "is_pr": { + "type": "boolean", + "title": "Is pull or merge request", + "description": "Is this environment a pull request / merge request", + "x-isDateTime": false, + "x-description": [ + "Is this environment a pull request / merge request" + ] + }, + "has_remote": { + "type": "boolean", + "title": "Has remote", + "description": "Does this environment have a remote repository", + "x-isDateTime": false, + "x-description": [ + "Does this environment have a remote repository" + ] + }, + "status": { + "type": "string", + "enum": [ + "active", + "deleting", + "dirty", + "inactive", + "paused" + ], + "title": "Status", + "description": "The status of the environment", + "x-isDateTime": false, + "x-description": [ + "The status of the environment" + ] + }, + "http_access": { + "type": "object", + "properties": { + "is_enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether http_access control is enabled", + "x-description": [ + "Whether http_access control is enabled" + ] + }, + "addresses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "permission": { + "type": "string", + "enum": [ + "allow", + "deny" + ], + "title": "Permission", + "description": "" + }, + "address": { + "type": "string", + "title": "Address", + "description": "IP address or CIDR" + } + }, + "required": [ + "permission", + "address" + ], + "additionalProperties": false + }, + "title": "Address grants", + "description": "" + }, + "basic_auth": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Basic auth grants", + "description": "" + } + }, + "required": [ + "is_enabled", + "addresses", + "basic_auth" + ], + "additionalProperties": false, + "title": "Http access permissions", + "description": "The Http access permissions for this environment", + "x-isDateTime": false, + "x-description": [ + "The Http access permissions for this environment" + ] + }, + "enable_smtp": { + "type": "boolean", + "title": "Enable SMTP", + "description": "Whether to configure SMTP for this environment", + "x-isDateTime": false, + "x-description": [ + "Whether to configure SMTP for this environment" + ] + }, + "restrict_robots": { + "type": "boolean", + "title": "Restrict robots", + "description": "Whether to restrict robots for this environment", + "x-isDateTime": false, + "x-description": [ + "Whether to restrict robots for this environment" + ] + }, + "edge_hostname": { + "type": "string", + "title": "Edge hostname", + "description": "The hostname to use as the CNAME", + "x-isDateTime": false, + "x-description": [ + "The hostname to use as the CNAME" + ] + }, + "deployment_state": { + "type": "object", + "properties": { + "last_deployment_successful": { + "type": "boolean", + "title": "Last deployment successful", + "description": "Whether the last deployment was successful", + "x-description": [ + "Whether the last deployment was successful" + ] + }, + "last_deployment_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Last deployment datetime", + "description": "Datetime of the last deployment", + "x-description": [ + "Datetime of the last deployment" + ] + }, + "last_autoscale_up_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Last autoscale up datetime", + "description": "Datetime of the last autoscale up deployment", + "x-description": [ + "Datetime of the last autoscale up deployment" + ] + }, + "last_autoscale_down_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Last autoscale down datetime", + "description": "Datetime of the last autoscale down deployment", + "x-description": [ + "Datetime of the last autoscale down deployment" + ] + }, + "crons": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Enabled or disabled", + "x-description": [ + "Enabled or disabled" + ] + }, + "status": { + "type": "string", + "enum": [ + "paused", + "running", + "sleeping" + ], + "title": "Status", + "description": "The status of the crons", + "x-description": [ + "The status of the crons" + ] + } + }, + "required": [ + "enabled", + "status" + ], + "additionalProperties": false, + "title": "Crons deployment state", + "description": "The crons deployment state", + "x-description": [ + "The crons deployment state" + ] + } + }, + "required": [ + "last_deployment_successful", + "last_deployment_at", + "last_autoscale_up_at", + "last_autoscale_down_at", + "crons" + ], + "additionalProperties": false, + "nullable": true, + "title": "Deployment state", + "description": "The environment deployment state", + "x-isDateTime": false, + "x-description": [ + "The environment deployment state" + ] + }, + "sizing": { + "type": "object", + "properties": { + "services": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "properties": { + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "Profile size of the service." + } + }, + "required": [ + "profile_size" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "" + }, + "instance_count": { + "type": "integer", + "nullable": true, + "title": "Instance count", + "description": "Instance replication count of this application" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "The size of the disk." + } + }, + "required": [ + "resources", + "instance_count", + "disk" + ], + "additionalProperties": false + }, + "title": "Services", + "description": "" + }, + "webapps": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "properties": { + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "Profile size of the service." + } + }, + "required": [ + "profile_size" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "" + }, + "instance_count": { + "type": "integer", + "nullable": true, + "title": "Instance count", + "description": "Instance replication count of this application" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "The size of the disk." + } + }, + "required": [ + "resources", + "instance_count", + "disk" + ], + "additionalProperties": false + }, + "title": "Web applications", + "description": "" + }, + "workers": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "properties": { + "profile_size": { + "type": "string", + "nullable": true, + "title": "Profile size", + "description": "Profile size of the service." + } + }, + "required": [ + "profile_size" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "" + }, + "instance_count": { + "type": "integer", + "nullable": true, + "title": "Instance count", + "description": "Instance replication count of this application" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk size", + "description": "The size of the disk." + } + }, + "required": [ + "resources", + "instance_count", + "disk" + ], + "additionalProperties": false + }, + "title": "Workers", + "description": "" + } + }, + "required": [ + "services", + "webapps", + "workers" + ], + "additionalProperties": false, + "nullable": true, + "title": "Sizing", + "description": "The environment sizing configuration", + "x-isDateTime": false, + "x-description": [ + "The environment sizing configuration" + ] + }, + "resources_overrides": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "services": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "nullable": true, + "title": "CPU", + "description": "" + }, + "memory": { + "type": "integer", + "nullable": true, + "title": "Memory", + "description": "" + }, + "disk": { + "type": "integer", + "nullable": true, + "title": "Disk", + "description": "" + } + }, + "required": [ + "cpu", + "memory", + "disk" + ], + "additionalProperties": false + }, + "title": "Pre-service resources overrides", + "description": "Per-service resources overrides." + }, + "starts_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Start date", + "description": "Date when the override will apply. When null, don't do an auto redeployment but still be effective to redeploys initiated otherwise." + }, + "ends_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "End date", + "description": "Date when the override will be reverted. When null, the overrides will never go out of effect." + }, + "redeployed_start": { + "type": "boolean", + "title": "Is starting redeploy activity fired", + "description": "Whether the starting redeploy activity has been fired for this override." + }, + "redeployed_end": { + "type": "boolean", + "title": "Is ending redeploy activity fired", + "description": "Whether the ending redeploy activity has been fired for this override." + } + }, + "required": [ + "services", + "starts_at", + "ends_at", + "redeployed_start", + "redeployed_end" + ], + "additionalProperties": false + }, + "title": "Resources overrides", + "description": "Resources overrides", + "x-isDateTime": false, + "x-description": [ + "Resources overrides" + ] + }, + "max_instance_count": { + "type": "integer", + "nullable": true, + "title": "Max instances", + "description": "Max number of instances for this environment", + "x-isDateTime": false, + "x-description": [ + "Max number of instances for this environment" + ] + }, + "last_active_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Last activity date", + "description": "Last activity date", + "x-isDateTime": true, + "x-description": [ + "Last activity date" + ] + }, + "last_backup_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Last backup date", + "description": "Last backup date", + "x-isDateTime": true, + "x-description": [ + "Last backup date" + ] + }, + "project": { + "type": "string", + "title": "Project", + "description": "The project the environment belongs to", + "x-isDateTime": false, + "x-description": [ + "The project the environment belongs to" + ] + }, + "is_main": { + "type": "boolean", + "title": "Is main environment", + "description": "Is this environment the main environment", + "x-isDateTime": false, + "x-description": [ + "Is this environment the main environment" + ] + }, + "is_dirty": { + "type": "boolean", + "title": "Is dirty", + "description": "Is there any pending activity on this environment", + "x-isDateTime": false, + "x-description": [ + "Is there any pending activity on this environment" + ] + }, + "has_staged_activities": { + "type": "boolean", + "title": "Has staged activities", + "description": "Is there any staged activity on this environment", + "x-isDateTime": false, + "x-description": [ + "Is there any staged activity on this environment" + ] + }, + "can_rolling_deploy": { + "type": "boolean", + "title": "Can perform rolling deployments", + "description": "If the environment has rolling deployments ready for use", + "x-isDateTime": false, + "x-description": [ + "If the environment has rolling deployments ready for use" + ] + }, + "supports_rolling_deployments": { + "type": "boolean", + "title": "Supports rolling deployments", + "description": "If the environment supports rolling deployments", + "x-isDateTime": false, + "x-description": [ + "If the environment supports rolling deployments" + ] + }, + "has_code": { + "type": "boolean", + "title": "Has code", + "description": "Does this environment have code", + "x-isDateTime": false, + "x-description": [ + "Does this environment have code" + ] + }, + "head_commit": { + "type": "string", + "nullable": true, + "title": "Head commit", + "description": "The SHA of the head commit for this environment", + "x-isDateTime": false, + "x-description": [ + "The SHA of the head commit for this environment" + ] + }, + "merge_info": { + "type": "object", + "properties": { + "commits_ahead": { + "type": "integer", + "nullable": true, + "title": "Commits ahead", + "description": "The amount of commits that are in the environment but not in the parent", + "x-description": [ + "The amount of commits that are in the environment but not in the parent" + ] + }, + "commits_behind": { + "type": "integer", + "nullable": true, + "title": "Commits behind", + "description": "The amount of commits that are in the parent but not in the environment", + "x-description": [ + "The amount of commits that are in the parent but not in the environment" + ] + }, + "parent_ref": { + "type": "string", + "nullable": true, + "title": "Parent ref", + "description": "The reference in Git for the parent environment", + "x-description": [ + "The reference in Git for the parent environment" + ] + } + }, + "required": [ + "commits_ahead", + "commits_behind", + "parent_ref" + ], + "additionalProperties": false, + "title": "Merge info", + "description": "The commit distance info between parent and child environments", + "x-isDateTime": false, + "x-description": [ + "The commit distance info between parent and child environments" + ] + }, + "has_deployment": { + "type": "boolean", + "title": "Has deployment", + "description": "Whether this environment had a successful deployment", + "x-isDateTime": false, + "x-description": [ + "Whether this environment had a successful deployment" + ] + }, + "supports_restrict_robots": { + "type": "boolean", + "title": "Supports restrict_robots", + "description": "Does this environment support configuring restrict_robots", + "x-isDateTime": false, + "x-description": [ + "Does this environment support configuring restrict_robots" + ] + } + }, + "required": [ + "id", + "created_at", + "updated_at", + "name", + "machine_name", + "title", + "attributes", + "type", + "parent", + "default_domain", + "has_domains", + "clone_parent_on_create", + "deployment_target", + "is_pr", + "has_remote", + "status", + "http_access", + "enable_smtp", + "restrict_robots", + "edge_hostname", + "deployment_state", + "sizing", + "resources_overrides", + "max_instance_count", + "last_active_at", + "last_backup_at", + "project", + "is_main", + "is_dirty", + "has_staged_activities", + "can_rolling_deploy", + "supports_rolling_deployments", + "has_code", + "head_commit", + "merge_info", + "has_deployment", + "supports_restrict_robots" + ], + "additionalProperties": false + }, + "EnvironmentActivateInput": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "properties": { + "init": { + "type": "string", + "enum": [ + "default", + "minimum", + "parent" + ], + "nullable": true, + "title": "Init Resources", + "description": "The resources used when activating an environment", + "x-description": [ + "The resources used when activating an environment" + ] + } + }, + "required": [ + "init" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "resources" + ], + "additionalProperties": false + }, + "EnvironmentBackupInput": { + "type": "object", + "properties": { + "safe": { + "type": "boolean", + "title": "Safe or live backup", + "description": "Take a safe or a live backup", + "x-isDateTime": false, + "x-description": [ + "Take a safe or a live backup" + ] + } + }, + "required": [ + "safe" + ], + "additionalProperties": false + }, + "EnvironmentBranchInput": { + "type": "object", + "properties": { + "title": { + "type": "string", + "title": "Title", + "description": "", + "x-isDateTime": false + }, + "name": { + "type": "string", + "title": "Name", + "description": "", + "x-isDateTime": false + }, + "clone_parent": { + "type": "boolean", + "title": "Clone parent", + "description": "Clone data from the parent environment", + "x-isDateTime": false, + "x-description": [ + "Clone data from the parent environment" + ] + }, + "type": { + "type": "string", + "enum": [ + "development", + "staging" + ], + "title": "Type", + "description": "The type of environment (`staging` or `development`)", + "x-isDateTime": false, + "x-description": [ + "The type of environment (`staging` or `development`)" + ] + }, + "resources": { + "type": "object", + "properties": { + "init": { + "type": "string", + "enum": [ + "default", + "minimum", + "parent" + ], + "nullable": true, + "title": "Init Resources", + "description": "The resources used when initializing services of the new environment", + "x-description": [ + "The resources used when initializing services of the new environment" + ] + } + }, + "required": [ + "init" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "title", + "name", + "clone_parent", + "type", + "resources" + ], + "additionalProperties": false + }, + "EnvironmentCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Environment" + } + }, + "EnvironmentDeployInput": { + "type": "object", + "properties": { + "strategy": { + "type": "string", + "enum": [ + "rolling", + "stopstart" + ], + "title": "Deployment strategy", + "description": "The deployment strategy (`rolling` or `stopstart`)", + "x-isDateTime": false, + "x-description": [ + "The deployment strategy (`rolling` or `stopstart`)" + ] + } + }, + "required": [ + "strategy" + ], + "additionalProperties": false + }, + "EnvironmentInitializeInput": { + "type": "object", + "properties": { + "profile": { + "type": "string", + "title": "Profile", + "description": "Name of the profile to show in the UI", + "x-isDateTime": false, + "x-description": [ + "Name of the profile to show in the UI" + ] + }, + "repository": { + "type": "string", + "title": "Repository", + "description": "Repository to clone from", + "x-isDateTime": false, + "x-description": [ + "Repository to clone from" + ] + }, + "config": { + "type": "string", + "nullable": true, + "title": "Configuration repository", + "description": "Repository to clone the configuration files from", + "x-isDateTime": false, + "x-description": [ + "Repository to clone the configuration files from" + ] + }, + "files": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string", + "title": "Path", + "description": "The path to the file." + }, + "mode": { + "type": "integer", + "title": "Mode", + "description": "The octal value of the file protection mode." + }, + "contents": { + "type": "string", + "title": "Contents", + "description": "The contents of the file (base64 encoded)." + } + }, + "required": [ + "path", + "mode", + "contents" + ], + "additionalProperties": false + }, + "title": "Files", + "description": "A list of files to add to the repository during initialization", + "x-isDateTime": false, + "x-description": [ + "A list of files to add to the repository during initialization" + ] + }, + "resources": { + "type": "object", + "properties": { + "init": { + "type": "string", + "enum": [ + "default", + "minimum" + ], + "nullable": true, + "title": "Init Resources", + "description": "The resources used when initializing the environment", + "x-description": [ + "The resources used when initializing the environment" + ] + } + }, + "required": [ + "init" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "profile", + "repository", + "config", + "files", + "resources" + ], + "additionalProperties": false + }, + "EnvironmentMergeInput": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "properties": { + "init": { + "type": "string", + "enum": [ + "child", + "default", + "manual", + "minimum" + ], + "nullable": true, + "title": "Init Resources", + "description": "The resources used when merging an environment", + "x-description": [ + "The resources used when merging an environment" + ] + } + }, + "required": [ + "init" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "resources" + ], + "additionalProperties": false + }, + "EnvironmentOperationInput": { + "type": "object", + "properties": { + "service": { + "type": "string", + "title": "Application or worker name", + "description": "The name of the application or worker to run the operation on", + "x-isDateTime": false, + "x-description": [ + "The name of the application or worker to run the operation on" + ] + }, + "operation": { + "type": "string", + "title": "Operation name", + "description": "The name of the operation", + "x-isDateTime": false, + "x-description": [ + "The name of the operation" + ] + }, + "parameters": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Operation parameters", + "description": "The parameters to run the operation with", + "x-isDateTime": false, + "x-description": [ + "The parameters to run the operation with" + ] + } + }, + "required": [ + "service", + "operation", + "parameters" + ], + "additionalProperties": false + }, + "EnvironmentPatch": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "The name of the environment", + "x-isDateTime": false, + "x-description": [ + "The name of the environment" + ] + }, + "title": { + "type": "string", + "title": "Title", + "description": "The title of the environment", + "x-isDateTime": false, + "x-description": [ + "The title of the environment" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "type": { + "type": "string", + "enum": [ + "development", + "production", + "staging" + ], + "title": "Type", + "description": "The type of environment (`production`, `staging` or `development`), if not provided, a default will be calculated", + "x-isDateTime": false, + "x-description": [ + "The type of environment (`production`, `staging` or `development`), if not provided, a default will be calculated" + ] + }, + "parent": { + "type": "string", + "nullable": true, + "title": "Parent environment", + "description": "The name of the parent environment", + "x-isDateTime": false, + "x-description": [ + "The name of the parent environment" + ] + }, + "clone_parent_on_create": { + "type": "boolean", + "title": "Clone parent on create", + "description": "Clone data when creating that environment", + "x-isDateTime": false, + "x-description": [ + "Clone data when creating that environment" + ] + }, + "http_access": { + "type": "object", + "properties": { + "is_enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether http_access control is enabled", + "x-description": [ + "Whether http_access control is enabled" + ] + }, + "addresses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "permission": { + "type": "string", + "enum": [ + "allow", + "deny" + ], + "title": "Permission", + "description": "" + }, + "address": { + "type": "string", + "title": "Address", + "description": "IP address or CIDR" + } + }, + "required": [ + "permission", + "address" + ], + "additionalProperties": false + }, + "title": "Address grants", + "description": "" + }, + "basic_auth": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Basic auth grants", + "description": "" + } + }, + "additionalProperties": false, + "title": "Http access permissions", + "description": "The Http access permissions for this environment", + "x-isDateTime": false, + "x-description": [ + "The Http access permissions for this environment" + ] + }, + "enable_smtp": { + "type": "boolean", + "title": "Enable SMTP", + "description": "Whether to configure SMTP for this environment", + "x-isDateTime": false, + "x-description": [ + "Whether to configure SMTP for this environment" + ] + }, + "restrict_robots": { + "type": "boolean", + "title": "Restrict robots", + "description": "Whether to restrict robots for this environment", + "x-isDateTime": false, + "x-description": [ + "Whether to restrict robots for this environment" + ] + } + }, + "additionalProperties": false + }, + "EnvironmentRestoreInput": { + "type": "object", + "properties": { + "environment_name": { + "type": "string", + "nullable": true, + "title": "Environment name", + "description": "", + "x-isDateTime": false + }, + "branch_from": { + "type": "string", + "nullable": true, + "title": "Branch from", + "description": "", + "x-isDateTime": false + }, + "restore_code": { + "type": "boolean", + "title": "Is code or data restored", + "description": "Whether we should restore the code or only the data", + "x-isDateTime": false, + "x-description": [ + "Whether we should restore the code or only the data" + ] + }, + "restore_resources": { + "type": "boolean", + "title": "Is resources restored", + "description": "Whether we should restore resources configuration from the backup", + "x-isDateTime": false, + "x-description": [ + "Whether we should restore resources configuration from the backup" + ] + }, + "resources": { + "type": "object", + "properties": { + "init": { + "type": "string", + "enum": [ + "backup", + "default", + "minimum", + "parent" + ], + "nullable": true, + "title": "Init Resources", + "description": "The resources used when initializing services of the environment", + "x-description": [ + "The resources used when initializing services of the environment" + ] + } + }, + "required": [ + "init" + ], + "additionalProperties": false, + "nullable": true, + "title": "Resources", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "environment_name", + "branch_from", + "restore_code", + "restore_resources", + "resources" + ], + "additionalProperties": false + }, + "EnvironmentSourceOperation": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "EnvironmentSourceOperation Identifier", + "description": "The identifier of EnvironmentSourceOperation", + "x-isDateTime": false, + "x-description": [ + "The identifier of EnvironmentSourceOperation" + ] + }, + "app": { + "type": "string", + "title": "Application name", + "description": "The name of the application", + "x-isDateTime": false, + "x-description": [ + "The name of the application" + ] + }, + "operation": { + "type": "string", + "title": "Source operation name", + "description": "The name of the source operation", + "x-isDateTime": false, + "x-description": [ + "The name of the source operation" + ] + }, + "command": { + "type": "string", + "title": "Command", + "description": "The command that will be triggered", + "x-isDateTime": false, + "x-description": [ + "The command that will be triggered" + ] + } + }, + "required": [ + "id", + "app", + "operation", + "command" + ], + "additionalProperties": false + }, + "EnvironmentSourceOperationCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnvironmentSourceOperation" + } + }, + "EnvironmentSourceOperationInput": { + "type": "object", + "properties": { + "operation": { + "type": "string", + "title": "Operation name", + "description": "The name of the operation to execute", + "x-isDateTime": false, + "x-description": [ + "The name of the operation to execute" + ] + }, + "variables": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": {} + }, + "title": "Variables", + "description": "The variables of the application.", + "x-isDateTime": false, + "x-description": [ + "The variables of the application." + ] + } + }, + "required": [ + "operation", + "variables" + ], + "additionalProperties": false + }, + "EnvironmentSynchronizeInput": { + "type": "object", + "properties": { + "synchronize_code": { + "type": "boolean", + "title": "Is code synchronized", + "description": "Synchronize code?", + "x-isDateTime": false, + "x-description": [ + "Synchronize code?" + ] + }, + "rebase": { + "type": "boolean", + "title": "Is code rebased", + "description": "Synchronize code by rebasing instead of merging", + "x-isDateTime": false, + "x-description": [ + "Synchronize code by rebasing instead of merging" + ] + }, + "synchronize_data": { + "type": "boolean", + "title": "Is data synchronized", + "description": "Synchronize data?", + "x-isDateTime": false, + "x-description": [ + "Synchronize data?" + ] + }, + "synchronize_resources": { + "type": "boolean", + "title": "Are resources synchronized", + "description": "Synchronize resources?", + "x-isDateTime": false, + "x-description": [ + "Synchronize resources?" + ] + } + }, + "required": [ + "synchronize_code", + "rebase", + "synchronize_data", + "synchronize_resources" + ], + "additionalProperties": false + }, + "EnvironmentType": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "EnvironmentType Identifier", + "description": "The identifier of EnvironmentType", + "x-isDateTime": false, + "x-description": [ + "The identifier of EnvironmentType" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + } + }, + "required": [ + "id", + "attributes" + ], + "additionalProperties": false + }, + "EnvironmentTypeCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnvironmentType" + } + }, + "EnvironmentVariable": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "EnvironmentVariable Identifier", + "description": "The identifier of EnvironmentVariable", + "x-isDateTime": false, + "x-description": [ + "The identifier of EnvironmentVariable" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the variable", + "x-isDateTime": false, + "x-description": [ + "Name of the variable" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "value": { + "type": "string", + "title": "Value", + "description": "Value of the variable", + "x-isDateTime": false, + "x-description": [ + "Value of the variable" + ] + }, + "is_json": { + "type": "boolean", + "title": "Is JSON", + "description": "The variable is a JSON string", + "x-isDateTime": false, + "x-description": [ + "The variable is a JSON string" + ] + }, + "is_sensitive": { + "type": "boolean", + "title": "Is Sensitive", + "description": "The variable is sensitive", + "x-isDateTime": false, + "x-description": [ + "The variable is sensitive" + ] + }, + "visible_build": { + "type": "boolean", + "title": "Is visible during build", + "description": "The variable is visible during build", + "x-isDateTime": false, + "x-description": [ + "The variable is visible during build" + ] + }, + "visible_runtime": { + "type": "boolean", + "title": "Visible at runtime", + "description": "The variable is visible at runtime", + "x-isDateTime": false, + "x-description": [ + "The variable is visible at runtime" + ] + }, + "application_scope": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Application Scope", + "description": "Applications that have access to this variable", + "x-isDateTime": false, + "x-description": [ + "Applications that have access to this variable" + ] + }, + "project": { + "type": "string", + "title": "Project name", + "description": "The name of the project", + "x-isDateTime": false, + "x-description": [ + "The name of the project" + ] + }, + "environment": { + "type": "string", + "title": "Environment name", + "description": "The name of the environment", + "x-isDateTime": false, + "x-description": [ + "The name of the environment" + ] + }, + "inherited": { + "type": "boolean", + "title": "Is inherited", + "description": "The variable is inherited from a parent environment", + "x-isDateTime": false, + "x-description": [ + "The variable is inherited from a parent environment" + ] + }, + "is_enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "The variable is enabled on this environment", + "x-isDateTime": false, + "x-description": [ + "The variable is enabled on this environment" + ] + }, + "is_inheritable": { + "type": "boolean", + "title": "Is inheritable", + "description": "The variable is inheritable to child environments", + "x-isDateTime": false, + "x-description": [ + "The variable is inheritable to child environments" + ] + } + }, + "required": [ + "id", + "created_at", + "updated_at", + "name", + "attributes", + "is_json", + "is_sensitive", + "visible_build", + "visible_runtime", + "application_scope", + "project", + "environment", + "inherited", + "is_enabled", + "is_inheritable" + ], + "additionalProperties": false + }, + "EnvironmentVariableCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnvironmentVariable" + } + }, + "EnvironmentVariableCreateInput": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Name of the variable", + "x-isDateTime": false, + "x-description": [ + "Name of the variable" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "value": { + "type": "string", + "title": "Value", + "description": "Value of the variable", + "x-isDateTime": false, + "x-description": [ + "Value of the variable" + ] + }, + "is_json": { + "type": "boolean", + "title": "Is JSON", + "description": "The variable is a JSON string", + "x-isDateTime": false, + "x-description": [ + "The variable is a JSON string" + ] + }, + "is_sensitive": { + "type": "boolean", + "title": "Is Sensitive", + "description": "The variable is sensitive", + "x-isDateTime": false, + "x-description": [ + "The variable is sensitive" + ] + }, + "visible_build": { + "type": "boolean", + "title": "Is visible during build", + "description": "The variable is visible during build", + "x-isDateTime": false, + "x-description": [ + "The variable is visible during build" + ] + }, + "visible_runtime": { + "type": "boolean", + "title": "Visible at runtime", + "description": "The variable is visible at runtime", + "x-isDateTime": false, + "x-description": [ + "The variable is visible at runtime" + ] + }, + "application_scope": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Application Scope", + "description": "Applications that have access to this variable", + "x-isDateTime": false, + "x-description": [ + "Applications that have access to this variable" + ] + }, + "is_enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "The variable is enabled on this environment", + "x-isDateTime": false, + "x-description": [ + "The variable is enabled on this environment" + ] + }, + "is_inheritable": { + "type": "boolean", + "title": "Is inheritable", + "description": "The variable is inheritable to child environments", + "x-isDateTime": false, + "x-description": [ + "The variable is inheritable to child environments" + ] + } + }, + "required": [ + "name", + "value" + ], + "additionalProperties": false + }, + "EnvironmentVariablePatch": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Name of the variable", + "x-isDateTime": false, + "x-description": [ + "Name of the variable" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "value": { + "type": "string", + "title": "Value", + "description": "Value of the variable", + "x-isDateTime": false, + "x-description": [ + "Value of the variable" + ] + }, + "is_json": { + "type": "boolean", + "title": "Is JSON", + "description": "The variable is a JSON string", + "x-isDateTime": false, + "x-description": [ + "The variable is a JSON string" + ] + }, + "is_sensitive": { + "type": "boolean", + "title": "Is Sensitive", + "description": "The variable is sensitive", + "x-isDateTime": false, + "x-description": [ + "The variable is sensitive" + ] + }, + "visible_build": { + "type": "boolean", + "title": "Is visible during build", + "description": "The variable is visible during build", + "x-isDateTime": false, + "x-description": [ + "The variable is visible during build" + ] + }, + "visible_runtime": { + "type": "boolean", + "title": "Visible at runtime", + "description": "The variable is visible at runtime", + "x-isDateTime": false, + "x-description": [ + "The variable is visible at runtime" + ] + }, + "application_scope": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Application Scope", + "description": "Applications that have access to this variable", + "x-isDateTime": false, + "x-description": [ + "Applications that have access to this variable" + ] + }, + "is_enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "The variable is enabled on this environment", + "x-isDateTime": false, + "x-description": [ + "The variable is enabled on this environment" + ] + }, + "is_inheritable": { + "type": "boolean", + "title": "Is inheritable", + "description": "The variable is inheritable to child environments", + "x-isDateTime": false, + "x-description": [ + "The variable is inheritable to child environments" + ] + } + }, + "additionalProperties": false + }, + "FastlyIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "FastlyIntegration Identifier", + "description": "The identifier of FastlyIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of FastlyIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Events", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to execute the hook on" + ] + }, + "excluded_environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Environments", + "description": "The environments to not execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to not execute the hook on" + ] + }, + "states": { + "type": "array", + "items": { + "type": "string" + }, + "title": "States", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "result": { + "type": "string", + "enum": [ + "*", + "failure", + "success" + ], + "title": "Result", + "description": "Result to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Result to execute the hook on" + ] + }, + "service_id": { + "type": "string", + "title": "Fastly Service ID", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "events", + "environments", + "excluded_environments", + "states", + "result", + "service_id" + ], + "additionalProperties": false + }, + "FastlyIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Events", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to execute the hook on" + ] + }, + "excluded_environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Environments", + "description": "The environments to not execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to not execute the hook on" + ] + }, + "states": { + "type": "array", + "items": { + "type": "string" + }, + "title": "States", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "result": { + "type": "string", + "enum": [ + "*", + "failure", + "success" + ], + "title": "Result", + "description": "Result to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Result to execute the hook on" + ] + }, + "token": { + "type": "string", + "title": "Token", + "description": "Fastly API Token", + "x-isDateTime": false, + "x-description": [ + "Fastly API Token" + ] + }, + "service_id": { + "type": "string", + "title": "Fastly Service ID", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "type", + "token", + "service_id" + ], + "additionalProperties": false + }, + "FastlyIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Events", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to execute the hook on" + ] + }, + "excluded_environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Environments", + "description": "The environments to not execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to not execute the hook on" + ] + }, + "states": { + "type": "array", + "items": { + "type": "string" + }, + "title": "States", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "result": { + "type": "string", + "enum": [ + "*", + "failure", + "success" + ], + "title": "Result", + "description": "Result to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Result to execute the hook on" + ] + }, + "token": { + "type": "string", + "title": "Token", + "description": "Fastly API Token", + "x-isDateTime": false, + "x-description": [ + "Fastly API Token" + ] + }, + "service_id": { + "type": "string", + "title": "Fastly Service ID", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "type", + "token", + "service_id" + ], + "additionalProperties": false + }, + "FoundationDeploymentTarget": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "FoundationDeploymentTarget Identifier", + "description": "The identifier of FoundationDeploymentTarget", + "x-isDateTime": false, + "x-description": [ + "The identifier of FoundationDeploymentTarget" + ] + }, + "type": { + "type": "string", + "enum": [ + "dedicated", + "enterprise", + "local" + ], + "title": "Deployment target type", + "description": "The type of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The type of the deployment target." + ] + }, + "name": { + "type": "string", + "title": "Deployment target name", + "description": "The name of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The name of the deployment target." + ] + }, + "hosts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true, + "title": "Host identifier", + "description": "The identifier of the host." + }, + "type": { + "type": "string", + "enum": [ + "core", + "satellite" + ], + "title": "Deployment type", + "description": "The type of the deployment to this host." + }, + "services": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "title": "Assigned services", + "description": "The services assigned to this host" + } + }, + "required": [ + "id", + "type", + "services" + ], + "additionalProperties": false + }, + "nullable": true, + "title": "Deployment hosts", + "description": "The hosts of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The hosts of the deployment target." + ] + }, + "use_dedicated_grid": { + "type": "boolean", + "title": "Whether the deployment should target dedicated Grid hosts.", + "description": "When true, the deployment will be pinned to Grid hosts dedicated to the environment using this deployment target.\n\nDedicated Grid hosts must be created prior to deploying the environment.\n\nThe constraints that will be set are as follows:\n\n* `cluster_type` is set to `environment-custom`.\n* `cluster` is set to the environment's cluster name.", + "x-isDateTime": false, + "x-description": [ + "When true, the deployment will be pinned to Grid hosts dedicated to the environment using this deployment target.", + "Dedicated Grid hosts must be created prior to deploying the environment. The constraints that will be set are as", + "follows: * `cluster_type` is set to `environment-custom`. * `cluster` is set to the environment's cluster name." + ] + }, + "storage_type": { + "type": "string", + "nullable": true, + "title": "Storage Type", + "description": "The storage type.", + "x-isDateTime": false, + "x-description": [ + "The storage type." + ] + } + }, + "required": [ + "type", + "name", + "hosts", + "use_dedicated_grid", + "storage_type" + ], + "additionalProperties": false + }, + "FoundationDeploymentTargetCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "dedicated", + "enterprise", + "local" + ], + "title": "Deployment target type", + "description": "The type of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The type of the deployment target." + ] + }, + "name": { + "type": "string", + "title": "Deployment target name", + "description": "The name of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The name of the deployment target." + ] + }, + "hosts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true, + "title": "Host identifier", + "description": "The identifier of the host." + }, + "type": { + "type": "string", + "enum": [ + "core", + "satellite" + ], + "title": "Deployment type", + "description": "The type of the deployment to this host." + }, + "services": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "title": "Assigned services", + "description": "The services assigned to this host" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + }, + "nullable": true, + "title": "Deployment hosts", + "description": "The hosts of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The hosts of the deployment target." + ] + }, + "use_dedicated_grid": { + "type": "boolean", + "title": "Whether the deployment should target dedicated Grid hosts.", + "description": "When true, the deployment will be pinned to Grid hosts dedicated to the environment using this deployment target.\n\nDedicated Grid hosts must be created prior to deploying the environment.\n\nThe constraints that will be set are as follows:\n\n* `cluster_type` is set to `environment-custom`.\n* `cluster` is set to the environment's cluster name.", + "x-isDateTime": false, + "x-description": [ + "When true, the deployment will be pinned to Grid hosts dedicated to the environment using this deployment target.", + "Dedicated Grid hosts must be created prior to deploying the environment. The constraints that will be set are as", + "follows: * `cluster_type` is set to `environment-custom`. * `cluster` is set to the environment's cluster name." + ] + } + }, + "required": [ + "type", + "name" + ], + "additionalProperties": false + }, + "FoundationDeploymentTargetPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "dedicated", + "enterprise", + "local" + ], + "title": "Deployment target type", + "description": "The type of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The type of the deployment target." + ] + }, + "name": { + "type": "string", + "title": "Deployment target name", + "description": "The name of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The name of the deployment target." + ] + }, + "hosts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true, + "title": "Host identifier", + "description": "The identifier of the host." + }, + "type": { + "type": "string", + "enum": [ + "core", + "satellite" + ], + "title": "Deployment type", + "description": "The type of the deployment to this host." + }, + "services": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "title": "Assigned services", + "description": "The services assigned to this host" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + }, + "nullable": true, + "title": "Deployment hosts", + "description": "The hosts of the deployment target.", + "x-isDateTime": false, + "x-description": [ + "The hosts of the deployment target." + ] + }, + "use_dedicated_grid": { + "type": "boolean", + "title": "Whether the deployment should target dedicated Grid hosts.", + "description": "When true, the deployment will be pinned to Grid hosts dedicated to the environment using this deployment target.\n\nDedicated Grid hosts must be created prior to deploying the environment.\n\nThe constraints that will be set are as follows:\n\n* `cluster_type` is set to `environment-custom`.\n* `cluster` is set to the environment's cluster name.", + "x-isDateTime": false, + "x-description": [ + "When true, the deployment will be pinned to Grid hosts dedicated to the environment using this deployment target.", + "Dedicated Grid hosts must be created prior to deploying the environment. The constraints that will be set are as", + "follows: * `cluster_type` is set to `environment-custom`. * `cluster` is set to the environment's cluster name." + ] + } + }, + "required": [ + "type", + "name" + ], + "additionalProperties": false + }, + "GitLabIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "GitLabIntegration Identifier", + "description": "The identifier of GitLabIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of GitLabIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "token_expires_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "'expires_at' value of the current token.", + "description": "", + "x-isDateTime": true + }, + "rotate_token": { + "type": "boolean", + "title": "Whether or not to rotate token automatically using Gitlab API.", + "description": "", + "x-isDateTime": false + }, + "rotate_token_validity_in_weeks": { + "type": "integer", + "title": "Validity in weeks of a new token after rotation.", + "description": "", + "x-isDateTime": false + }, + "base_url": { + "type": "string", + "title": "GitLab Base URL", + "description": "The base URL of the GitLab installation.", + "x-isDateTime": false, + "x-description": [ + "The base URL of the GitLab installation." + ] + }, + "project": { + "type": "string", + "title": "Project", + "description": "The GitLab project (in the form `namespace/repo`).", + "x-isDateTime": false, + "x-description": [ + "The GitLab project (in the form `namespace/repo`)." + ] + }, + "build_merge_requests": { + "type": "boolean", + "title": "Build Merge Requests", + "description": "Whether or not to build merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build merge requests." + ] + }, + "build_wip_merge_requests": { + "type": "boolean", + "title": "Build WIP Merge Requests", + "description": "Whether or not to build work in progress merge requests (requires `build_merge_requests`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build work in progress merge requests (requires `build_merge_requests`)." + ] + }, + "merge_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone Parent Data", + "description": "Whether or not to clone parent data when building merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building merge requests." + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "fetch_branches", + "prune_branches", + "environment_init_resources", + "token_expires_at", + "rotate_token", + "rotate_token_validity_in_weeks", + "base_url", + "project", + "build_merge_requests", + "build_wip_merge_requests", + "merge_requests_clone_parent_data" + ], + "additionalProperties": false + }, + "GitLabIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "token": { + "type": "string", + "title": "GitLab Private Token", + "description": "The GitLab private token.", + "x-isDateTime": false, + "x-description": [ + "The GitLab private token." + ] + }, + "rotate_token": { + "type": "boolean", + "title": "Whether or not to rotate token automatically using Gitlab API.", + "description": "", + "x-isDateTime": false + }, + "rotate_token_validity_in_weeks": { + "type": "integer", + "title": "Validity in weeks of a new token after rotation.", + "description": "", + "x-isDateTime": false + }, + "base_url": { + "type": "string", + "title": "GitLab Base URL", + "description": "The base URL of the GitLab installation.", + "x-isDateTime": false, + "x-description": [ + "The base URL of the GitLab installation." + ] + }, + "project": { + "type": "string", + "title": "Project", + "description": "The GitLab project (in the form `namespace/repo`).", + "x-isDateTime": false, + "x-description": [ + "The GitLab project (in the form `namespace/repo`)." + ] + }, + "build_merge_requests": { + "type": "boolean", + "title": "Build Merge Requests", + "description": "Whether or not to build merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build merge requests." + ] + }, + "build_wip_merge_requests": { + "type": "boolean", + "title": "Build WIP Merge Requests", + "description": "Whether or not to build work in progress merge requests (requires `build_merge_requests`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build work in progress merge requests (requires `build_merge_requests`)." + ] + }, + "merge_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone Parent Data", + "description": "Whether or not to clone parent data when building merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building merge requests." + ] + } + }, + "required": [ + "type", + "token", + "project" + ], + "additionalProperties": false + }, + "GitLabIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "token": { + "type": "string", + "title": "GitLab Private Token", + "description": "The GitLab private token.", + "x-isDateTime": false, + "x-description": [ + "The GitLab private token." + ] + }, + "rotate_token": { + "type": "boolean", + "title": "Whether or not to rotate token automatically using Gitlab API.", + "description": "", + "x-isDateTime": false + }, + "rotate_token_validity_in_weeks": { + "type": "integer", + "title": "Validity in weeks of a new token after rotation.", + "description": "", + "x-isDateTime": false + }, + "base_url": { + "type": "string", + "title": "GitLab Base URL", + "description": "The base URL of the GitLab installation.", + "x-isDateTime": false, + "x-description": [ + "The base URL of the GitLab installation." + ] + }, + "project": { + "type": "string", + "title": "Project", + "description": "The GitLab project (in the form `namespace/repo`).", + "x-isDateTime": false, + "x-description": [ + "The GitLab project (in the form `namespace/repo`)." + ] + }, + "build_merge_requests": { + "type": "boolean", + "title": "Build Merge Requests", + "description": "Whether or not to build merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build merge requests." + ] + }, + "build_wip_merge_requests": { + "type": "boolean", + "title": "Build WIP Merge Requests", + "description": "Whether or not to build work in progress merge requests (requires `build_merge_requests`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build work in progress merge requests (requires `build_merge_requests`)." + ] + }, + "merge_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone Parent Data", + "description": "Whether or not to clone parent data when building merge requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building merge requests." + ] + } + }, + "required": [ + "type", + "token", + "project" + ], + "additionalProperties": false + }, + "GithubIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "GithubIntegration Identifier", + "description": "The identifier of GithubIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of GithubIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "base_url": { + "type": "string", + "nullable": true, + "title": "Base URL", + "description": "The base URL of the Github API endpoint.", + "x-isDateTime": false, + "x-description": [ + "The base URL of the Github API endpoint." + ] + }, + "repository": { + "type": "string", + "title": "Repository", + "description": "The GitHub repository (in the form `user/repo`).", + "x-isDateTime": false, + "x-description": [ + "The GitHub repository (in the form `user/repo`)." + ] + }, + "build_pull_requests": { + "type": "boolean", + "title": "Build Pull Requests", + "description": "Whether or not to build pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build pull requests." + ] + }, + "build_draft_pull_requests": { + "type": "boolean", + "title": "Build Draft Pull Requests", + "description": "Whether or not to build draft pull requests (requires `build_pull_requests`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build draft pull requests (requires `build_pull_requests`)." + ] + }, + "build_pull_requests_post_merge": { + "type": "boolean", + "title": "Build PR Post-Merge", + "description": "Whether to build pull requests post-merge (if true) or pre-merge (if false).", + "x-isDateTime": false, + "x-description": [ + "Whether to build pull requests post-merge (if true) or pre-merge (if false)." + ] + }, + "pull_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone Parent Data", + "description": "Whether or not to clone parent data when building pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building pull requests." + ] + }, + "token_type": { + "type": "string", + "enum": [ + "classic_personal_token", + "github_app" + ], + "title": "Token Type", + "description": "The type of the token of this GitHub integration", + "x-isDateTime": false, + "x-description": [ + "The type of the token of this GitHub integration" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "fetch_branches", + "prune_branches", + "environment_init_resources", + "base_url", + "repository", + "build_pull_requests", + "build_draft_pull_requests", + "build_pull_requests_post_merge", + "pull_requests_clone_parent_data", + "token_type" + ], + "additionalProperties": false + }, + "GithubIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "token": { + "type": "string", + "title": "Token", + "description": "The GitHub token.", + "x-isDateTime": false, + "x-description": [ + "The GitHub token." + ] + }, + "base_url": { + "type": "string", + "nullable": true, + "title": "Base URL", + "description": "The base URL of the Github API endpoint.", + "x-isDateTime": false, + "x-description": [ + "The base URL of the Github API endpoint." + ] + }, + "repository": { + "type": "string", + "title": "Repository", + "description": "The GitHub repository (in the form `user/repo`).", + "x-isDateTime": false, + "x-description": [ + "The GitHub repository (in the form `user/repo`)." + ] + }, + "build_pull_requests": { + "type": "boolean", + "title": "Build Pull Requests", + "description": "Whether or not to build pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build pull requests." + ] + }, + "build_draft_pull_requests": { + "type": "boolean", + "title": "Build Draft Pull Requests", + "description": "Whether or not to build draft pull requests (requires `build_pull_requests`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build draft pull requests (requires `build_pull_requests`)." + ] + }, + "build_pull_requests_post_merge": { + "type": "boolean", + "title": "Build PR Post-Merge", + "description": "Whether to build pull requests post-merge (if true) or pre-merge (if false).", + "x-isDateTime": false, + "x-description": [ + "Whether to build pull requests post-merge (if true) or pre-merge (if false)." + ] + }, + "pull_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone Parent Data", + "description": "Whether or not to clone parent data when building pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building pull requests." + ] + } + }, + "required": [ + "type", + "token", + "repository" + ], + "additionalProperties": false + }, + "GithubIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "fetch_branches": { + "type": "boolean", + "title": "Fetch Branches", + "description": "Whether or not to fetch branches.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to fetch branches." + ] + }, + "prune_branches": { + "type": "boolean", + "title": "Prune Branches", + "description": "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to remove branches that disappeared remotely (requires `fetch_branches`)." + ] + }, + "environment_init_resources": { + "type": "string", + "enum": [ + "default", + "manual", + "minimum", + "parent" + ], + "title": "Environment Init Resources", + "description": "The resources used when initializing a new service", + "x-isDateTime": false, + "x-description": [ + "The resources used when initializing a new service" + ] + }, + "token": { + "type": "string", + "title": "Token", + "description": "The GitHub token.", + "x-isDateTime": false, + "x-description": [ + "The GitHub token." + ] + }, + "base_url": { + "type": "string", + "nullable": true, + "title": "Base URL", + "description": "The base URL of the Github API endpoint.", + "x-isDateTime": false, + "x-description": [ + "The base URL of the Github API endpoint." + ] + }, + "repository": { + "type": "string", + "title": "Repository", + "description": "The GitHub repository (in the form `user/repo`).", + "x-isDateTime": false, + "x-description": [ + "The GitHub repository (in the form `user/repo`)." + ] + }, + "build_pull_requests": { + "type": "boolean", + "title": "Build Pull Requests", + "description": "Whether or not to build pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build pull requests." + ] + }, + "build_draft_pull_requests": { + "type": "boolean", + "title": "Build Draft Pull Requests", + "description": "Whether or not to build draft pull requests (requires `build_pull_requests`).", + "x-isDateTime": false, + "x-description": [ + "Whether or not to build draft pull requests (requires `build_pull_requests`)." + ] + }, + "build_pull_requests_post_merge": { + "type": "boolean", + "title": "Build PR Post-Merge", + "description": "Whether to build pull requests post-merge (if true) or pre-merge (if false).", + "x-isDateTime": false, + "x-description": [ + "Whether to build pull requests post-merge (if true) or pre-merge (if false)." + ] + }, + "pull_requests_clone_parent_data": { + "type": "boolean", + "title": "Clone Parent Data", + "description": "Whether or not to clone parent data when building pull requests.", + "x-isDateTime": false, + "x-description": [ + "Whether or not to clone parent data when building pull requests." + ] + } + }, + "required": [ + "type", + "token", + "repository" + ], + "additionalProperties": false + }, + "HealthWebHookIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "HealthWebHookIntegration Identifier", + "description": "The identifier of HealthWebHookIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of HealthWebHookIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "url": { + "type": "string", + "title": "WebHook URL", + "description": "The URL of the webhook", + "x-isDateTime": false, + "x-description": [ + "The URL of the webhook" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "url" + ], + "additionalProperties": false + }, + "HealthWebHookIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "shared_key": { + "type": "string", + "nullable": true, + "title": "Shared Key", + "description": "The JWS shared secret key", + "x-isDateTime": false, + "x-description": [ + "The JWS shared secret key" + ] + }, + "url": { + "type": "string", + "title": "WebHook URL", + "description": "The URL of the webhook", + "x-isDateTime": false, + "x-description": [ + "The URL of the webhook" + ] + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "HealthWebHookIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "shared_key": { + "type": "string", + "nullable": true, + "title": "Shared Key", + "description": "The JWS shared secret key", + "x-isDateTime": false, + "x-description": [ + "The JWS shared secret key" + ] + }, + "url": { + "type": "string", + "title": "WebHook URL", + "description": "The URL of the webhook", + "x-isDateTime": false, + "x-description": [ + "The URL of the webhook" + ] + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "HttpLogIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "HttpLogIntegration Identifier", + "description": "The identifier of HttpLogIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of HttpLogIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "HTTP endpoint", + "description": "", + "x-isDateTime": false + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "HTTP Headers", + "description": "HTTP headers to use in POST requests", + "x-isDateTime": false, + "x-description": [ + "HTTP headers to use in POST requests" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "extra", + "url", + "headers", + "tls_verify", + "excluded_services" + ], + "additionalProperties": false + }, + "HttpLogIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "HTTP endpoint", + "description": "", + "x-isDateTime": false + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "HTTP Headers", + "description": "HTTP headers to use in POST requests", + "x-isDateTime": false, + "x-description": [ + "HTTP headers to use in POST requests" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "HttpLogIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "HTTP endpoint", + "description": "", + "x-isDateTime": false + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "HTTP Headers", + "description": "HTTP headers to use in POST requests", + "x-isDateTime": false, + "x-description": [ + "HTTP headers to use in POST requests" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "Integration": { + "oneOf": [ + { + "$ref": "#/components/schemas/BitbucketIntegration" + }, + { + "$ref": "#/components/schemas/BitbucketServerIntegration" + }, + { + "$ref": "#/components/schemas/BlackfireIntegration" + }, + { + "$ref": "#/components/schemas/FastlyIntegration" + }, + { + "$ref": "#/components/schemas/GithubIntegration" + }, + { + "$ref": "#/components/schemas/GitLabIntegration" + }, + { + "$ref": "#/components/schemas/EmailIntegration" + }, + { + "$ref": "#/components/schemas/PagerDutyIntegration" + }, + { + "$ref": "#/components/schemas/SlackIntegration" + }, + { + "$ref": "#/components/schemas/HealthWebHookIntegration" + }, + { + "$ref": "#/components/schemas/HttpLogIntegration" + }, + { + "$ref": "#/components/schemas/NewRelicIntegration" + }, + { + "$ref": "#/components/schemas/HttpLogIntegration" + }, + { + "$ref": "#/components/schemas/ScriptIntegration" + }, + { + "$ref": "#/components/schemas/SplunkIntegration" + }, + { + "$ref": "#/components/schemas/SumologicIntegration" + }, + { + "$ref": "#/components/schemas/SyslogIntegration" + }, + { + "$ref": "#/components/schemas/WebHookIntegration" + } + ] + }, + "IntegrationCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Integration" + } + }, + "IntegrationCreateInput": { + "oneOf": [ + { + "$ref": "#/components/schemas/BitbucketIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/BitbucketServerIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/BlackfireIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/FastlyIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/GithubIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/GitLabIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/EmailIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/PagerDutyIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/SlackIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/HealthWebHookIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/HttpLogIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/NewRelicIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/HttpLogIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/ScriptIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/SplunkIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/SumologicIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/SyslogIntegrationCreateInput" + }, + { + "$ref": "#/components/schemas/WebHookIntegrationCreateInput" + } + ] + }, + "IntegrationPatch": { + "oneOf": [ + { + "$ref": "#/components/schemas/BitbucketIntegrationPatch" + }, + { + "$ref": "#/components/schemas/BitbucketServerIntegrationPatch" + }, + { + "$ref": "#/components/schemas/BlackfireIntegrationPatch" + }, + { + "$ref": "#/components/schemas/FastlyIntegrationPatch" + }, + { + "$ref": "#/components/schemas/GithubIntegrationPatch" + }, + { + "$ref": "#/components/schemas/GitLabIntegrationPatch" + }, + { + "$ref": "#/components/schemas/EmailIntegrationPatch" + }, + { + "$ref": "#/components/schemas/PagerDutyIntegrationPatch" + }, + { + "$ref": "#/components/schemas/SlackIntegrationPatch" + }, + { + "$ref": "#/components/schemas/HealthWebHookIntegrationPatch" + }, + { + "$ref": "#/components/schemas/HttpLogIntegrationPatch" + }, + { + "$ref": "#/components/schemas/NewRelicIntegrationPatch" + }, + { + "$ref": "#/components/schemas/HttpLogIntegrationPatch" + }, + { + "$ref": "#/components/schemas/ScriptIntegrationPatch" + }, + { + "$ref": "#/components/schemas/SplunkIntegrationPatch" + }, + { + "$ref": "#/components/schemas/SumologicIntegrationPatch" + }, + { + "$ref": "#/components/schemas/SyslogIntegrationPatch" + }, + { + "$ref": "#/components/schemas/WebHookIntegrationPatch" + } + ] + }, + "NewRelicIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "NewRelicIntegration Identifier", + "description": "The identifier of NewRelicIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of NewRelicIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "The NewRelic Logs endpoint", + "description": "", + "x-isDateTime": false + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "extra", + "url", + "tls_verify", + "excluded_services" + ], + "additionalProperties": false + }, + "NewRelicIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "The NewRelic Logs endpoint", + "description": "", + "x-isDateTime": false + }, + "license_key": { + "type": "string", + "title": "License Key", + "description": "The NewRelic Logs License Key", + "x-isDateTime": false, + "x-description": [ + "The NewRelic Logs License Key" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type", + "url", + "license_key" + ], + "additionalProperties": false + }, + "NewRelicIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "The NewRelic Logs endpoint", + "description": "", + "x-isDateTime": false + }, + "license_key": { + "type": "string", + "title": "License Key", + "description": "The NewRelic Logs License Key", + "x-isDateTime": false, + "x-description": [ + "The NewRelic Logs License Key" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type", + "url", + "license_key" + ], + "additionalProperties": false + }, + "PagerDutyIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "PagerDutyIntegration Identifier", + "description": "The identifier of PagerDutyIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of PagerDutyIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "routing_key": { + "type": "string", + "title": "Routing Key", + "description": "The PagerDuty routing key", + "x-isDateTime": false, + "x-description": [ + "The PagerDuty routing key" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "routing_key" + ], + "additionalProperties": false + }, + "PagerDutyIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "routing_key": { + "type": "string", + "title": "Routing Key", + "description": "The PagerDuty routing key", + "x-isDateTime": false, + "x-description": [ + "The PagerDuty routing key" + ] + } + }, + "required": [ + "type", + "routing_key" + ], + "additionalProperties": false + }, + "PagerDutyIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "routing_key": { + "type": "string", + "title": "Routing Key", + "description": "The PagerDuty routing key", + "x-isDateTime": false, + "x-description": [ + "The PagerDuty routing key" + ] + } + }, + "required": [ + "type", + "routing_key" + ], + "additionalProperties": false + }, + "ProdDomainStorage": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "ProdDomainStorage Identifier", + "description": "The identifier of ProdDomainStorage", + "x-isDateTime": false, + "x-description": [ + "The identifier of ProdDomainStorage" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Domain type", + "description": "", + "x-isDateTime": false + }, + "project": { + "type": "string", + "title": "Project name", + "description": "", + "x-isDateTime": false + }, + "name": { + "type": "string", + "title": "Domain name", + "description": "", + "x-isDateTime": false + }, + "registered_name": { + "type": "string", + "title": "Claimed domain name", + "description": "", + "x-isDateTime": false + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "is_default": { + "type": "boolean", + "title": "Is Default", + "description": "Is this domain default", + "x-isDateTime": false, + "x-description": [ + "Is this domain default" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "name", + "attributes" + ], + "additionalProperties": false + }, + "ProdDomainStorageCreateInput": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Domain name", + "description": "", + "x-isDateTime": false + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "is_default": { + "type": "boolean", + "title": "Is Default", + "description": "Is this domain default", + "x-isDateTime": false, + "x-description": [ + "Is this domain default" + ] + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "ProdDomainStoragePatch": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "is_default": { + "type": "boolean", + "title": "Is Default", + "description": "Is this domain default", + "x-isDateTime": false, + "x-description": [ + "Is this domain default" + ] + } + }, + "additionalProperties": false + }, + "Project": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Project Identifier", + "description": "The identifier of Project", + "x-isDateTime": false, + "x-description": [ + "The identifier of Project" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "title": { + "type": "string", + "title": "Title", + "description": "The title of the project", + "x-isDateTime": false, + "x-description": [ + "The title of the project" + ] + }, + "description": { + "type": "string", + "title": "Description", + "description": "The description of the project", + "x-isDateTime": false, + "x-description": [ + "The description of the project" + ] + }, + "owner": { + "type": "string", + "title": "Owner", + "description": "The owner of the project", + "deprecated": true, + "x-stability": "DEPRECATED", + "x-isDateTime": false, + "x-description": [ + "The owner of the project" + ] + }, + "namespace": { + "type": "string", + "nullable": true, + "title": "Namespace", + "description": "The namespace the project belongs in", + "x-stability": "EXPERIMENTAL", + "x-isDateTime": false, + "x-description": [ + "The namespace the project belongs in" + ] + }, + "organization": { + "type": "string", + "nullable": true, + "title": "Organization", + "description": "The organization the project belongs in", + "x-stability": "EXPERIMENTAL", + "x-isDateTime": false, + "x-description": [ + "The organization the project belongs in" + ] + }, + "default_branch": { + "type": "string", + "nullable": true, + "title": "Default branch", + "description": "The default branch of the project", + "x-isDateTime": false, + "x-description": [ + "The default branch of the project" + ] + }, + "status": { + "type": "object", + "properties": { + "code": { + "type": "string", + "title": "Status code", + "description": "" + }, + "message": { + "type": "string", + "title": "Status text", + "description": "" + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": false, + "title": "Status", + "description": "The status of the project", + "x-isDateTime": false, + "x-description": [ + "The status of the project" + ] + }, + "timezone": { + "type": "string", + "title": "Timezone", + "description": "Timezone of the project", + "x-isDateTime": false, + "x-description": [ + "Timezone of the project" + ] + }, + "region": { + "type": "string", + "title": "Region", + "description": "The region of the project", + "x-isDateTime": false, + "x-description": [ + "The region of the project" + ] + }, + "repository": { + "type": "object", + "properties": { + "url": { + "type": "string", + "title": "Git URL", + "description": "" + }, + "client_ssh_key": { + "type": "string", + "nullable": true, + "title": "SSH Key", + "description": "SSH Key used to access external private repositories.", + "x-description": [ + "SSH Key used to access external private repositories." + ] + } + }, + "required": [ + "url", + "client_ssh_key" + ], + "additionalProperties": false, + "title": "Repository information", + "description": "The repository information of the project", + "x-isDateTime": false, + "x-description": [ + "The repository information of the project" + ] + }, + "default_domain": { + "type": "string", + "nullable": true, + "title": "Default domain", + "description": "The default domain of the project", + "x-isDateTime": false, + "x-description": [ + "The default domain of the project" + ] + }, + "subscription": { + "type": "object", + "properties": { + "license_uri": { + "type": "string", + "title": "Subscription URI", + "description": "URI of the subscription", + "x-description": [ + "URI of the subscription" + ] + }, + "plan": { + "type": "string", + "enum": [ + "2xlarge", + "2xlarge-high-memory", + "4xlarge", + "8xlarge", + "development", + "large", + "large-high-memory", + "medium", + "medium-high-memory", + "standard", + "standard-high-memory", + "xlarge", + "xlarge-high-memory" + ], + "title": "Plan level", + "description": "" + }, + "environments": { + "type": "integer", + "title": "Environments number", + "description": "Number of environments", + "x-description": [ + "Number of environments" + ] + }, + "storage": { + "type": "integer", + "title": "Storage", + "description": "Size of storage (in MB)", + "x-description": [ + "Size of storage (in MB)" + ] + }, + "included_users": { + "type": "integer", + "title": "Included users", + "description": "Number of users", + "x-description": [ + "Number of users" + ] + }, + "subscription_management_uri": { + "type": "string", + "title": "Subscription management URI", + "description": "URI for managing the subscription", + "x-description": [ + "URI for managing the subscription" + ] + }, + "restricted": { + "type": "boolean", + "title": "Is subscription attributes frozen", + "description": "True if subscription attributes, like number of users, are frozen", + "x-description": [ + "True if subscription attributes, like number of users, are frozen" + ] + }, + "suspended": { + "type": "boolean", + "title": "Is subscription suspended", + "description": "Whether or not the subscription is suspended", + "x-description": [ + "Whether or not the subscription is suspended" + ] + }, + "user_licenses": { + "type": "integer", + "title": "Current number of users", + "description": "Current number of users", + "x-description": [ + "Current number of users" + ] + }, + "resources": { + "type": "object", + "properties": { + "container_profiles": { + "type": "boolean", + "title": "Is Container profiles enabled", + "description": "Enable support for customizable container profiles.", + "x-description": [ + "Enable support for customizable container profiles." + ] + }, + "production": { + "type": "object", + "properties": { + "legacy_development": { + "type": "boolean", + "title": "Legacy development sizing", + "description": "Enable legacy development sizing for this environment type.", + "x-description": [ + "Enable legacy development sizing for this environment type." + ] + }, + "max_cpu": { + "type": "number", + "format": "float", + "nullable": true, + "title": "Maximum CPU units", + "description": "Maximum number of allocated CPU units.", + "x-description": [ + "Maximum number of allocated CPU units." + ] + }, + "max_memory": { + "type": "integer", + "nullable": true, + "title": "Maximum RAM", + "description": "Maximum amount of allocated RAM.", + "x-description": [ + "Maximum amount of allocated RAM." + ] + }, + "max_environments": { + "type": "integer", + "nullable": true, + "title": "Maximum environments", + "description": "Maximum number of environments", + "x-description": [ + "Maximum number of environments" + ] + } + }, + "required": [ + "legacy_development", + "max_cpu", + "max_memory", + "max_environments" + ], + "additionalProperties": false, + "title": "Production resources", + "description": "Resources for production environments", + "x-description": [ + "Resources for production environments" + ] + }, + "development": { + "type": "object", + "properties": { + "legacy_development": { + "type": "boolean", + "title": "Legacy development sizing", + "description": "Enable legacy development sizing for this environment type.", + "x-description": [ + "Enable legacy development sizing for this environment type." + ] + }, + "max_cpu": { + "type": "number", + "format": "float", + "nullable": true, + "title": "Maximum CPU units", + "description": "Maximum number of allocated CPU units.", + "x-description": [ + "Maximum number of allocated CPU units." + ] + }, + "max_memory": { + "type": "integer", + "nullable": true, + "title": "Maximum RAM", + "description": "Maximum amount of allocated RAM.", + "x-description": [ + "Maximum amount of allocated RAM." + ] + }, + "max_environments": { + "type": "integer", + "nullable": true, + "title": "Maximum environments", + "description": "Maximum number of environments", + "x-description": [ + "Maximum number of environments" + ] + } + }, + "required": [ + "legacy_development", + "max_cpu", + "max_memory", + "max_environments" + ], + "additionalProperties": false, + "title": "Development resources", + "description": "Resources for development environments", + "x-description": [ + "Resources for development environments" + ] + } + }, + "required": [ + "container_profiles", + "production", + "development" + ], + "additionalProperties": false, + "title": "Resources limits", + "description": "Resources limits", + "x-description": [ + "Resources limits" + ] + }, + "resource_validation_url": { + "type": "string", + "title": "Resource validation URL", + "description": "URL for resources validation", + "x-description": [ + "URL for resources validation" + ] + }, + "image_types": { + "type": "object", + "properties": { + "only": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Allowed image types", + "description": "Image types to be allowed use.", + "x-description": [ + "Image types to be allowed use." + ] + }, + "exclude": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Denied image types", + "description": "Image types to be denied use.", + "x-description": [ + "Image types to be denied use." + ] + } + }, + "additionalProperties": false, + "title": "Image type restrictions", + "description": "Restricted and denied image types", + "x-description": [ + "Restricted and denied image types" + ] + } + }, + "required": [ + "license_uri", + "storage", + "included_users", + "subscription_management_uri", + "restricted", + "suspended", + "user_licenses" + ], + "additionalProperties": false, + "title": "Subscription information", + "description": "The subscription information of the project", + "x-isDateTime": false, + "x-description": [ + "The subscription information of the project" + ] + } + }, + "required": [ + "id", + "created_at", + "updated_at", + "attributes", + "title", + "description", + "owner", + "namespace", + "organization", + "default_branch", + "status", + "timezone", + "region", + "repository", + "default_domain", + "subscription" + ], + "additionalProperties": false + }, + "ProjectCapabilities": { + "type": "object", + "properties": { + "custom_domains": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "If true, custom domains can be added to the project.", + "x-description": [ + "If true, custom domains can be added to the project." + ] + }, + "environments_with_domains_limit": { + "type": "integer", + "title": "Domains limit", + "description": "Limit on the amount of non-production environments that can have domains set", + "x-description": [ + "Limit on the amount of non-production environments that can have domains set" + ] + } + }, + "required": [ + "enabled", + "environments_with_domains_limit" + ], + "additionalProperties": false, + "title": "Custom Domains", + "description": "", + "x-isDateTime": false + }, + "source_operations": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "If true, source operations can be triggered.", + "x-description": [ + "If true, source operations can be triggered." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "Source Operations", + "description": "", + "x-isDateTime": false + }, + "runtime_operations": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "If true, runtime operations can be triggered.", + "x-description": [ + "If true, runtime operations can be triggered." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "Runtime Operations", + "description": "", + "x-isDateTime": false + }, + "outbound_firewall": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "If true, outbound firewall can be used.", + "x-description": [ + "If true, outbound firewall can be used." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "Outbound Firewall", + "description": "", + "x-isDateTime": false + }, + "metrics": { + "type": "object", + "properties": { + "max_range": { + "type": "string", + "title": "Max range", + "description": "Limit on the maximum time range allowed in metrics retrieval", + "x-description": [ + "Limit on the maximum time range allowed in metrics retrieval" + ] + } + }, + "required": [ + "max_range" + ], + "additionalProperties": false, + "title": "Metrics", + "description": "", + "x-isDateTime": false + }, + "logs_forwarding": { + "type": "object", + "properties": { + "max_extra_payload_size": { + "type": "integer", + "title": "Max extra payload size", + "description": "Limit on the maximum size for the custom extra attributes added to the forwarded logs payload", + "x-description": [ + "Limit on the maximum size for the custom extra attributes added to the forwarded logs payload" + ] + } + }, + "required": [ + "max_extra_payload_size" + ], + "additionalProperties": false, + "title": "Logs Forwarding", + "description": "", + "x-isDateTime": false + }, + "guaranteed_resources": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "If true, guaranteed resources can be used", + "x-description": [ + "If true, guaranteed resources can be used" + ] + }, + "instance_limit": { + "type": "integer", + "title": "Instance limit", + "description": "Instance limit for guaranteed resources", + "x-description": [ + "Instance limit for guaranteed resources" + ] + } + }, + "required": [ + "enabled", + "instance_limit" + ], + "additionalProperties": false, + "title": "Guaranteed Resources", + "description": "", + "x-isDateTime": false + }, + "images": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "available": { + "type": "boolean", + "title": "Available", + "description": "The image is available for deployment" + } + }, + "required": [ + "available" + ], + "additionalProperties": false + } + }, + "title": "Images", + "description": "", + "x-isDateTime": false + }, + "instance_limit": { + "type": "integer", + "title": "Instance limit", + "description": "Maximum number of instance per service", + "x-isDateTime": false, + "x-description": [ + "Maximum number of instance per service" + ] + }, + "build_resources": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "If true, build resources can be modified.", + "x-description": [ + "If true, build resources can be modified." + ] + }, + "max_cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "" + }, + "max_memory": { + "type": "integer", + "title": "Memory", + "description": "" + } + }, + "required": [ + "enabled", + "max_cpu", + "max_memory" + ], + "additionalProperties": false, + "title": "Build Resources", + "description": "", + "x-isDateTime": false + }, + "data_retention": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "If true, data retention configuration can be modified.", + "x-description": [ + "If true, data retention configuration can be modified." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "Data Retention", + "description": "", + "x-isDateTime": false + }, + "autoscaling": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "If true, autoscaling can be configured.", + "x-description": [ + "If true, autoscaling can be configured." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "Autoscaling", + "description": "", + "x-isDateTime": false + }, + "integrations": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "If true, integrations can be used", + "x-description": [ + "If true, integrations can be used" + ] + }, + "config": { + "type": "object", + "properties": { + "newrelic": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "New Relic", + "description": "New Relic log-forwarding integration configurations", + "x-description": [ + "New Relic log-forwarding integration configurations" + ] + }, + "sumologic": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Sumo Logic", + "description": "Sumo Logic log-forwarding integration configurations", + "x-description": [ + "Sumo Logic log-forwarding integration configurations" + ] + }, + "splunk": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Splunk", + "description": "Splunk log-forwarding integration configurations", + "x-description": [ + "Splunk log-forwarding integration configurations" + ] + }, + "httplog": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "HTTP log-forwarding", + "description": "HTTP log-forwarding integration configurations", + "x-description": [ + "HTTP log-forwarding integration configurations" + ] + }, + "syslog": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Syslog", + "description": "Syslog log-forwarding integration configurations", + "x-description": [ + "Syslog log-forwarding integration configurations" + ] + }, + "webhook": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Webhook", + "description": "Webhook integration configurations", + "x-description": [ + "Webhook integration configurations" + ] + }, + "script": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Script", + "description": "Script integration configurations", + "x-description": [ + "Script integration configurations" + ] + }, + "github": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "GitHub", + "description": "GitHub integration configurations", + "x-description": [ + "GitHub integration configurations" + ] + }, + "gitlab": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "GitLab", + "description": "GitLab integration configurations", + "x-description": [ + "GitLab integration configurations" + ] + }, + "bitbucket": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Bitbucket", + "description": "Bitbucket integration configurations", + "x-description": [ + "Bitbucket integration configurations" + ] + }, + "bitbucket_server": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Bitbucket Server", + "description": "Bitbucket server integration configurations", + "x-description": [ + "Bitbucket server integration configurations" + ] + }, + "health.email": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Health Email", + "description": "Health Email notification integration configurations", + "x-description": [ + "Health Email notification integration configurations" + ] + }, + "health.webhook": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Health WebHook", + "description": "" + }, + "health.pagerduty": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Health PagerDuty", + "description": "Health PagerDuty notification integration configurations", + "x-description": [ + "Health PagerDuty notification integration configurations" + ] + }, + "health.slack": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Health Slack", + "description": "Health Slack notification integration configurations", + "x-description": [ + "Health Slack notification integration configurations" + ] + }, + "cdn.fastly": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Fastly CDN", + "description": "Fastly CDN integration configurations", + "x-description": [ + "Fastly CDN integration configurations" + ] + }, + "blackfire": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "Blackfire", + "description": "Blackfire integration configurations", + "x-description": [ + "Blackfire integration configurations" + ] + }, + "otlplog": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "The integration is enabled.", + "x-description": [ + "The integration is enabled." + ] + }, + "role": { + "type": "string", + "title": "Role", + "description": "Minimum required role for creating the integration.", + "x-description": [ + "Minimum required role for creating the integration." + ] + } + }, + "additionalProperties": false, + "title": "OpenTelemetry", + "description": "OpenTelemetry log-forwarding integration configurations", + "x-description": [ + "OpenTelemetry log-forwarding integration configurations" + ] + } + }, + "additionalProperties": false, + "title": "Config", + "description": "" + }, + "allowed_integrations": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Allowed Integrations", + "description": "List of integrations allowed to be created", + "x-description": [ + "List of integrations allowed to be created" + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "Integrations", + "description": "", + "x-isDateTime": false + } + }, + "required": [ + "metrics", + "logs_forwarding", + "guaranteed_resources", + "images", + "instance_limit", + "build_resources", + "data_retention", + "autoscaling" + ], + "additionalProperties": false + }, + "ProjectPatch": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "title": { + "type": "string", + "title": "Title", + "description": "The title of the project", + "x-isDateTime": false, + "x-description": [ + "The title of the project" + ] + }, + "description": { + "type": "string", + "title": "Description", + "description": "The description of the project", + "x-isDateTime": false, + "x-description": [ + "The description of the project" + ] + }, + "default_branch": { + "type": "string", + "nullable": true, + "title": "Default branch", + "description": "The default branch of the project", + "x-isDateTime": false, + "x-description": [ + "The default branch of the project" + ] + }, + "timezone": { + "type": "string", + "title": "Timezone", + "description": "Timezone of the project", + "x-isDateTime": false, + "x-description": [ + "Timezone of the project" + ] + }, + "region": { + "type": "string", + "title": "Region", + "description": "The region of the project", + "x-isDateTime": false, + "x-description": [ + "The region of the project" + ] + }, + "default_domain": { + "type": "string", + "nullable": true, + "title": "Default domain", + "description": "The default domain of the project", + "x-isDateTime": false, + "x-description": [ + "The default domain of the project" + ] + } + }, + "additionalProperties": false + }, + "ProjectSettings": { + "type": "object", + "properties": { + "initialize": { + "type": "object", + "title": "Initialization key", + "description": "", + "x-isDateTime": false + }, + "product_name": { + "type": "string", + "title": "Product Name", + "description": "The name of the product.", + "x-isDateTime": false, + "x-description": [ + "The name of the product." + ] + }, + "product_code": { + "type": "string", + "title": "Product Code", + "description": "The lowercase ASCII code of the product.", + "x-isDateTime": false, + "x-description": [ + "The lowercase ASCII code of the product." + ] + }, + "ui_uri_template": { + "type": "string", + "title": "UI URI Template", + "description": "The template of the project UI uri", + "x-isDateTime": false, + "x-description": [ + "The template of the project UI uri" + ] + }, + "variables_prefix": { + "type": "string", + "title": "Variables Prefix", + "description": "The prefix of the generated environment variables.", + "x-isDateTime": false, + "x-description": [ + "The prefix of the generated environment variables." + ] + }, + "bot_email": { + "type": "string", + "title": "Bot Email", + "description": "The email of the bot.", + "x-isDateTime": false, + "x-description": [ + "The email of the bot." + ] + }, + "application_config_file": { + "type": "string", + "title": "Application Config File", + "description": "The name of the application-specific configuration file.", + "x-isDateTime": false, + "x-description": [ + "The name of the application-specific configuration file." + ] + }, + "project_config_dir": { + "type": "string", + "title": "Project Config Directory", + "description": "The name of the project configuration directory.", + "x-isDateTime": false, + "x-description": [ + "The name of the project configuration directory." + ] + }, + "use_drupal_defaults": { + "type": "boolean", + "title": "Use Drupal Defaults", + "description": "Whether to use the default Drupal-centric configuration files when missing from the repository.", + "x-isDateTime": false, + "x-description": [ + "Whether to use the default Drupal-centric configuration files when missing from the repository." + ] + }, + "use_legacy_subdomains": { + "type": "boolean", + "title": "Use Legacy Subdomains", + "description": "Whether to use legacy subdomain scheme, that replaces `.` by `---` in development subdomains.", + "x-isDateTime": false, + "x-description": [ + "Whether to use legacy subdomain scheme, that replaces `.` by `---` in development subdomains." + ] + }, + "development_service_size": { + "type": "string", + "enum": [ + "2XL", + "4XL", + "L", + "M", + "S", + "XL" + ], + "title": "Development Service Size", + "description": "The size of development services.", + "x-isDateTime": false, + "x-description": [ + "The size of development services." + ] + }, + "development_application_size": { + "type": "string", + "enum": [ + "2XL", + "4XL", + "L", + "M", + "S", + "XL" + ], + "title": "Development Application Size", + "description": "The size of development applications.", + "x-isDateTime": false, + "x-description": [ + "The size of development applications." + ] + }, + "enable_certificate_provisioning": { + "type": "boolean", + "title": "Enable Certificate Provisioning", + "description": "Enable automatic certificate provisioning.", + "x-isDateTime": false, + "x-description": [ + "Enable automatic certificate provisioning." + ] + }, + "certificate_style": { + "type": "string", + "enum": [ + "ecdsa", + "rsa" + ], + "title": "Certificate Style", + "description": "", + "x-isDateTime": false + }, + "certificate_renewal_activity": { + "type": "boolean", + "title": "Certificate Renewal Activity", + "description": "Create an activity for certificate renewal", + "x-isDateTime": false, + "x-description": [ + "Create an activity for certificate renewal" + ] + }, + "development_domain_template": { + "type": "string", + "nullable": true, + "title": "Development Domain Template", + "description": "The template of the development domain, can include {project} and {environment} placeholders.", + "x-isDateTime": false, + "x-description": [ + "The template of the development domain, can include {project} and {environment} placeholders." + ] + }, + "enable_state_api_deployments": { + "type": "boolean", + "title": "Enable State API Deployments", + "description": "Enable the State API-driven deployments on regions that support them.", + "x-isDateTime": false, + "x-description": [ + "Enable the State API-driven deployments on regions that support them." + ] + }, + "temporary_disk_size": { + "type": "integer", + "nullable": true, + "title": "Temporary Disk Size", + "description": "Set the size of the temporary disk (/tmp, in MB).", + "x-isDateTime": false, + "x-description": [ + "Set the size of the temporary disk (/tmp, in MB)." + ] + }, + "local_disk_size": { + "type": "integer", + "nullable": true, + "title": "Local Disk Size", + "description": "Set the size of the instance disk (in MB).", + "x-isDateTime": false, + "x-description": [ + "Set the size of the instance disk (in MB)." + ] + }, + "cron_minimum_interval": { + "type": "integer", + "title": "Minimum cron interval", + "description": "Minimum interval between cron runs (in minutes)", + "x-isDateTime": false, + "x-description": [ + "Minimum interval between cron runs (in minutes)" + ] + }, + "cron_maximum_jitter": { + "type": "integer", + "title": "Maximum cron jitter", + "description": "Maximum jitter inserted in cron runs (in minutes)", + "x-isDateTime": false, + "x-description": [ + "Maximum jitter inserted in cron runs (in minutes)" + ] + }, + "cron_production_expiry_interval": { + "type": "integer", + "title": "Cron Production Expiry Interval", + "description": "The interval (in days) for which cron activity and logs are kept around", + "x-isDateTime": false, + "x-description": [ + "The interval (in days) for which cron activity and logs are kept around" + ] + }, + "cron_non_production_expiry_interval": { + "type": "integer", + "title": "Cron Non-Production Expiry Interval", + "description": "The interval (in days) for which cron activity and logs are kept around", + "x-isDateTime": false, + "x-description": [ + "The interval (in days) for which cron activity and logs are kept around" + ] + }, + "concurrency_limits": { + "type": "object", + "additionalProperties": { + "type": "integer", + "nullable": true + }, + "title": "Concurrency Limits", + "description": "The concurrency limits applied to different kind of activities", + "x-isDateTime": false, + "x-description": [ + "The concurrency limits applied to different kind of activities" + ] + }, + "flexible_build_cache": { + "type": "boolean", + "title": "Enable Flexible Build Cache", + "description": "Enable the flexible build cache implementation", + "x-isDateTime": false, + "x-description": [ + "Enable the flexible build cache implementation" + ] + }, + "strict_configuration": { + "type": "boolean", + "title": "Enable Strict Configuration", + "description": "Strict configuration validation.", + "x-isDateTime": false, + "x-description": [ + "Strict configuration validation." + ] + }, + "has_sleepy_crons": { + "type": "boolean", + "title": "Enable sleepy crons.", + "description": "", + "x-isDateTime": false + }, + "crons_in_git": { + "type": "boolean", + "title": "Enable crons from git.", + "description": "", + "x-isDateTime": false + }, + "custom_error_template": { + "type": "string", + "nullable": true, + "title": "Custom error template", + "description": "Custom error template for the router.", + "x-isDateTime": false, + "x-description": [ + "Custom error template for the router." + ] + }, + "app_error_page_template": { + "type": "string", + "nullable": true, + "title": "Application error template", + "description": "Custom error template for the application.", + "x-isDateTime": false, + "x-description": [ + "Custom error template for the application." + ] + }, + "environment_name_strategy": { + "type": "string", + "enum": [ + "hash", + "name-and-hash" + ], + "title": "Environment Name Strategy", + "description": "The strategy used to generate environment machine names", + "x-isDateTime": false, + "x-description": [ + "The strategy used to generate environment machine names" + ] + }, + "data_retention": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "max_backups": { + "type": "integer", + "title": "Maximum Backups", + "description": "The maximum number of backups per environment" + }, + "default_config": { + "type": "object", + "properties": { + "manual_count": { + "type": "integer", + "title": "Manual Count", + "description": "The number of manual backups to keep." + }, + "schedule": { + "type": "array", + "items": { + "type": "object", + "properties": { + "interval": { + "type": "string", + "title": "Interval", + "description": "The policy interval specification." + }, + "count": { + "type": "integer", + "title": "Count", + "description": "The number of backups to keep under this interval." + } + }, + "required": [ + "interval", + "count" + ], + "additionalProperties": false + }, + "title": "Schedule", + "description": "The backup schedule specification." + } + }, + "required": [ + "manual_count", + "schedule" + ], + "additionalProperties": false, + "title": "Default Config", + "description": "", + "x-stability": "EXPERIMENTAL" + } + }, + "required": [ + "max_backups", + "default_config" + ], + "additionalProperties": false + }, + "nullable": true, + "title": "Data retention configuration", + "description": "Data retention configuration", + "x-isDateTime": false, + "x-description": [ + "Data retention configuration" + ] + }, + "enable_codesource_integration_push": { + "type": "boolean", + "title": "Enable pushing commits", + "description": "Enable pushing commits to codesource integration.", + "x-isDateTime": false, + "x-description": [ + "Enable pushing commits to codesource integration." + ] + }, + "enforce_mfa": { + "type": "boolean", + "title": "Enforce multi-factor authentication.", + "description": "Enforce multi-factor authentication.", + "x-isDateTime": false, + "x-description": [ + "Enforce multi-factor authentication." + ] + }, + "systemd": { + "type": "boolean", + "title": "Use systemd", + "description": "Use systemd images.", + "x-isDateTime": false, + "x-description": [ + "Use systemd images." + ] + }, + "router_gen2": { + "type": "boolean", + "title": "Router v2", + "description": "Use the router v2 image.", + "x-isDateTime": false, + "x-description": [ + "Use the router v2 image." + ] + }, + "build_resources": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "" + }, + "memory": { + "type": "integer", + "title": "Memory", + "description": "" + } + }, + "required": [ + "cpu", + "memory" + ], + "additionalProperties": false, + "title": "Build Resources", + "description": "", + "x-isDateTime": false + }, + "outbound_restrictions_default_policy": { + "type": "string", + "enum": [ + "allow", + "deny" + ], + "title": "Outbound Restrictions Default Policy", + "description": "The default policy for firewall outbound restrictions", + "x-isDateTime": false, + "x-description": [ + "The default policy for firewall outbound restrictions" + ] + }, + "self_upgrade": { + "type": "boolean", + "title": "Self Upgrade", + "description": "Whether self-upgrades are enabled", + "x-isDateTime": false, + "x-description": [ + "Whether self-upgrades are enabled" + ] + }, + "self_upgrade_latest_major": { + "type": "boolean", + "title": "Whether to check for n+1 major version when self-upgrades are enabled", + "description": "", + "x-isDateTime": false + }, + "additional_hosts": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Additional Hosts", + "description": "A mapping of hostname to ip address to be added to the container's hosts file", + "x-isDateTime": false, + "x-description": [ + "A mapping of hostname to ip address to be added to the container's hosts file" + ] + }, + "max_allowed_routes": { + "type": "integer", + "title": "Maximum allowed routes", + "description": "Maximum number of routes allowed", + "x-isDateTime": false, + "x-description": [ + "Maximum number of routes allowed" + ] + }, + "max_allowed_redirects_paths": { + "type": "integer", + "title": "Maximum allowed redirect paths", + "description": "Maximum number of redirect paths allowed", + "x-isDateTime": false, + "x-description": [ + "Maximum number of redirect paths allowed" + ] + }, + "enable_incremental_backups": { + "type": "boolean", + "title": "Enable incremental backups", + "description": "Enable incremental backups on regions that support them.", + "x-isDateTime": false, + "x-description": [ + "Enable incremental backups on regions that support them." + ] + }, + "sizing_api_enabled": { + "type": "boolean", + "title": "Enable sizing api", + "description": "Enable sizing api.", + "x-isDateTime": false, + "x-description": [ + "Enable sizing api." + ] + }, + "enable_cache_grace_period": { + "type": "boolean", + "title": "Enable cache grace period", + "description": "Enable cache grace period.", + "x-isDateTime": false, + "x-description": [ + "Enable cache grace period." + ] + }, + "enable_zero_downtime_deployments": { + "type": "boolean", + "title": "Enable zero-downtime deployments", + "description": "Enable zero-downtime deployments for resource-only changes.", + "x-isDateTime": false, + "x-description": [ + "Enable zero-downtime deployments for resource-only changes." + ] + }, + "enable_admin_agent": { + "type": "boolean", + "title": "Enable admin agent", + "description": "", + "x-isDateTime": false + }, + "certifier_url": { + "type": "string", + "title": "Certifier URL", + "description": "The certifier url", + "x-isDateTime": false, + "x-description": [ + "The certifier url" + ] + }, + "centralized_permissions": { + "type": "boolean", + "title": "Centralized Permissions", + "description": "Whether centralized permissions are enabled", + "x-isDateTime": false, + "x-description": [ + "Whether centralized permissions are enabled" + ] + }, + "glue_server_max_request_size": { + "type": "integer", + "title": "Glue Server Max Request Size", + "description": "Maximum size of request to glue-server (in MB)", + "x-isDateTime": false, + "x-description": [ + "Maximum size of request to glue-server (in MB)" + ] + }, + "persistent_endpoints_ssh": { + "type": "boolean", + "title": "Persistent Endpoints SSH", + "description": "Enable SSH access update with persistent endpoint", + "x-isDateTime": false, + "x-description": [ + "Enable SSH access update with persistent endpoint" + ] + }, + "persistent_endpoints_ssl_certificates": { + "type": "boolean", + "title": "Persistent Endpoints SSL Certificates", + "description": "Enable SSL certificate update with persistent endpoint", + "x-isDateTime": false, + "x-description": [ + "Enable SSL certificate update with persistent endpoint" + ] + }, + "enable_disk_health_monitoring": { + "type": "boolean", + "title": "Enable disk health monitoring", + "description": "", + "x-isDateTime": false + }, + "enable_paused_environments": { + "type": "boolean", + "title": "Enable paused environments", + "description": "", + "x-isDateTime": false + }, + "enable_unified_configuration": { + "type": "boolean", + "title": "Enable unified configuration files", + "description": "", + "x-isDateTime": false + }, + "enable_routes_tracing": { + "type": "boolean", + "title": "Enable routes tracing", + "description": "Enable tracing support in routes", + "x-isDateTime": false, + "x-description": [ + "Enable tracing support in routes" + ] + }, + "image_deployment_validation": { + "type": "boolean", + "title": "Image Deployment Validation", + "description": "Enable extended deployment validation by images", + "x-isDateTime": false, + "x-description": [ + "Enable extended deployment validation by images" + ] + }, + "support_generic_images": { + "type": "boolean", + "title": "Support composable images", + "description": "", + "x-isDateTime": false + }, + "enable_github_app_token_exchange": { + "type": "boolean", + "title": "Enable GitHub App token exchange", + "description": "Enable fetching the GitHub App token from SIA.", + "x-isDateTime": false, + "x-description": [ + "Enable fetching the GitHub App token from SIA." + ] + }, + "continuous_profiling": { + "type": "object", + "properties": { + "supported_runtimes": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Supported runtimes", + "description": "List of images supported for continuous profiling", + "x-description": [ + "List of images supported for continuous profiling" + ] + } + }, + "required": [ + "supported_runtimes" + ], + "additionalProperties": false, + "title": "Continuous profiling configuration", + "description": "The continuous profiling configuration", + "x-isDateTime": false, + "x-description": [ + "The continuous profiling configuration" + ] + }, + "disable_agent_error_reporter": { + "type": "boolean", + "title": "Disable agent error reporter", + "description": "", + "x-isDateTime": false + }, + "requires_domain_ownership": { + "type": "boolean", + "title": "Require domain ownership", + "description": "Require ownership proof before domains are added to environments.", + "x-isDateTime": false, + "x-description": [ + "Require ownership proof before domains are added to environments." + ] + }, + "enable_guaranteed_resources": { + "type": "boolean", + "title": "Enable guaranteed resources feature", + "description": "Enable guaranteed resources feature", + "x-isDateTime": false, + "x-description": [ + "Enable guaranteed resources feature" + ] + }, + "git_server": { + "type": "object", + "properties": { + "push_size_hard_limit": { + "type": "integer", + "title": "Push Size Hard Limit", + "description": "Push Size Reject Limit", + "x-description": [ + "Push Size Reject Limit" + ] + } + }, + "required": [ + "push_size_hard_limit" + ], + "additionalProperties": false, + "title": "Git Server configuration", + "description": "", + "x-isDateTime": false + }, + "activity_logs_max_size": { + "type": "integer", + "title": "Activity Logs Max Size", + "description": "The maximum size of activity logs in bytes. This limit is applied on the pre-compressed log size.", + "x-isDateTime": false, + "x-description": [ + "The maximum size of activity logs in bytes. This limit is applied on the pre-compressed log size." + ] + }, + "allow_manual_deployments": { + "type": "boolean", + "title": "Allow Manual Deployments", + "description": "If deployments can be manual, i.e. explicitly triggered by user.", + "x-isDateTime": false, + "x-description": [ + "If deployments can be manual, i.e. explicitly triggered by user." + ] + }, + "allow_rolling_deployments": { + "type": "boolean", + "title": "Allow Rolling Deployments", + "description": "If the project can use rolling deployments.", + "x-isDateTime": false, + "x-description": [ + "If the project can use rolling deployments." + ] + }, + "allow_burst": { + "type": "boolean", + "title": "Allow burst", + "description": "", + "x-isDateTime": false + }, + "router_resources": { + "type": "object", + "properties": { + "baseline_cpu": { + "type": "number", + "format": "float", + "title": "Baseline CPU", + "description": "Router baseline CPU for flex plan", + "x-description": [ + "Router baseline CPU for flex plan" + ] + }, + "baseline_memory": { + "type": "integer", + "title": "Baseline Memory", + "description": "Router baseline memory (MB) for flex plan", + "x-description": [ + "Router baseline memory (MB) for flex plan" + ] + }, + "max_cpu": { + "type": "number", + "format": "float", + "title": "Max CPU", + "description": "Router max CPU for flex plan", + "x-description": [ + "Router max CPU for flex plan" + ] + }, + "max_memory": { + "type": "integer", + "title": "Max Memory", + "description": "Router max memory (MB) for flex plan", + "x-description": [ + "Router max memory (MB) for flex plan" + ] + } + }, + "required": [ + "baseline_cpu", + "baseline_memory", + "max_cpu", + "max_memory" + ], + "additionalProperties": false, + "title": "Router Resources", + "description": "Router resource settings for flex plan", + "x-isDateTime": false, + "x-description": [ + "Router resource settings for flex plan" + ] + } + }, + "required": [ + "initialize", + "product_name", + "product_code", + "ui_uri_template", + "variables_prefix", + "bot_email", + "application_config_file", + "project_config_dir", + "use_drupal_defaults", + "use_legacy_subdomains", + "development_service_size", + "development_application_size", + "enable_certificate_provisioning", + "certificate_style", + "certificate_renewal_activity", + "development_domain_template", + "enable_state_api_deployments", + "temporary_disk_size", + "local_disk_size", + "cron_minimum_interval", + "cron_maximum_jitter", + "cron_production_expiry_interval", + "cron_non_production_expiry_interval", + "concurrency_limits", + "flexible_build_cache", + "strict_configuration", + "has_sleepy_crons", + "crons_in_git", + "custom_error_template", + "app_error_page_template", + "environment_name_strategy", + "data_retention", + "enable_codesource_integration_push", + "enforce_mfa", + "systemd", + "router_gen2", + "build_resources", + "outbound_restrictions_default_policy", + "self_upgrade", + "self_upgrade_latest_major", + "additional_hosts", + "max_allowed_routes", + "max_allowed_redirects_paths", + "enable_incremental_backups", + "sizing_api_enabled", + "enable_cache_grace_period", + "enable_zero_downtime_deployments", + "enable_admin_agent", + "certifier_url", + "centralized_permissions", + "glue_server_max_request_size", + "persistent_endpoints_ssh", + "persistent_endpoints_ssl_certificates", + "enable_disk_health_monitoring", + "enable_paused_environments", + "enable_unified_configuration", + "enable_routes_tracing", + "image_deployment_validation", + "support_generic_images", + "enable_github_app_token_exchange", + "continuous_profiling", + "disable_agent_error_reporter", + "requires_domain_ownership", + "enable_guaranteed_resources", + "git_server", + "activity_logs_max_size", + "allow_manual_deployments", + "allow_rolling_deployments", + "allow_burst", + "router_resources" + ], + "additionalProperties": false + }, + "ProjectSettingsPatch": { + "type": "object", + "properties": { + "initialize": { + "type": "object", + "title": "Initialization key", + "description": "", + "x-isDateTime": false + }, + "data_retention": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "max_backups": { + "type": "integer", + "title": "Maximum Backups", + "description": "The maximum number of backups per environment" + }, + "default_config": { + "type": "object", + "properties": { + "manual_count": { + "type": "integer", + "title": "Manual Count", + "description": "The number of manual backups to keep." + }, + "schedule": { + "type": "array", + "items": { + "type": "object", + "properties": { + "interval": { + "type": "string", + "title": "Interval", + "description": "The policy interval specification." + }, + "count": { + "type": "integer", + "title": "Count", + "description": "The number of backups to keep under this interval." + } + }, + "required": [ + "interval", + "count" + ], + "additionalProperties": false + }, + "title": "Schedule", + "description": "The backup schedule specification." + } + }, + "additionalProperties": false, + "title": "Default Config", + "description": "", + "x-stability": "EXPERIMENTAL" + } + }, + "required": [ + "default_config" + ], + "additionalProperties": false + }, + "nullable": true, + "title": "Data retention configuration", + "description": "Data retention configuration", + "x-isDateTime": false, + "x-description": [ + "Data retention configuration" + ] + }, + "build_resources": { + "type": "object", + "properties": { + "cpu": { + "type": "number", + "format": "float", + "title": "CPU", + "description": "" + }, + "memory": { + "type": "integer", + "title": "Memory", + "description": "" + } + }, + "additionalProperties": false, + "title": "Build Resources", + "description": "", + "x-isDateTime": false + } + }, + "additionalProperties": false + }, + "ProjectVariable": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "ProjectVariable Identifier", + "description": "The identifier of ProjectVariable", + "x-isDateTime": false, + "x-description": [ + "The identifier of ProjectVariable" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the variable", + "x-isDateTime": false, + "x-description": [ + "Name of the variable" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "value": { + "type": "string", + "title": "Value", + "description": "Value of the variable", + "x-isDateTime": false, + "x-description": [ + "Value of the variable" + ] + }, + "is_json": { + "type": "boolean", + "title": "Is JSON", + "description": "The variable is a JSON string", + "x-isDateTime": false, + "x-description": [ + "The variable is a JSON string" + ] + }, + "is_sensitive": { + "type": "boolean", + "title": "Is Sensitive", + "description": "The variable is sensitive", + "x-isDateTime": false, + "x-description": [ + "The variable is sensitive" + ] + }, + "visible_build": { + "type": "boolean", + "title": "Visible during build", + "description": "The variable is visible during build", + "x-isDateTime": false, + "x-description": [ + "The variable is visible during build" + ] + }, + "visible_runtime": { + "type": "boolean", + "title": "Visible at runtime", + "description": "The variable is visible at runtime", + "x-isDateTime": false, + "x-description": [ + "The variable is visible at runtime" + ] + }, + "application_scope": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Application Scope", + "description": "Applications that have access to this variable", + "x-isDateTime": false, + "x-description": [ + "Applications that have access to this variable" + ] + } + }, + "required": [ + "id", + "created_at", + "updated_at", + "name", + "attributes", + "is_json", + "is_sensitive", + "visible_build", + "visible_runtime", + "application_scope" + ], + "additionalProperties": false + }, + "ProjectVariableCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectVariable" + } + }, + "ProjectVariableCreateInput": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Name of the variable", + "x-isDateTime": false, + "x-description": [ + "Name of the variable" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "value": { + "type": "string", + "title": "Value", + "description": "Value of the variable", + "x-isDateTime": false, + "x-description": [ + "Value of the variable" + ] + }, + "is_json": { + "type": "boolean", + "title": "Is JSON", + "description": "The variable is a JSON string", + "x-isDateTime": false, + "x-description": [ + "The variable is a JSON string" + ] + }, + "is_sensitive": { + "type": "boolean", + "title": "Is Sensitive", + "description": "The variable is sensitive", + "x-isDateTime": false, + "x-description": [ + "The variable is sensitive" + ] + }, + "visible_build": { + "type": "boolean", + "title": "Visible during build", + "description": "The variable is visible during build", + "x-isDateTime": false, + "x-description": [ + "The variable is visible during build" + ] + }, + "visible_runtime": { + "type": "boolean", + "title": "Visible at runtime", + "description": "The variable is visible at runtime", + "x-isDateTime": false, + "x-description": [ + "The variable is visible at runtime" + ] + }, + "application_scope": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Application Scope", + "description": "Applications that have access to this variable", + "x-isDateTime": false, + "x-description": [ + "Applications that have access to this variable" + ] + } + }, + "required": [ + "name", + "value" + ], + "additionalProperties": false + }, + "ProjectVariablePatch": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Name of the variable", + "x-isDateTime": false, + "x-description": [ + "Name of the variable" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "value": { + "type": "string", + "title": "Value", + "description": "Value of the variable", + "x-isDateTime": false, + "x-description": [ + "Value of the variable" + ] + }, + "is_json": { + "type": "boolean", + "title": "Is JSON", + "description": "The variable is a JSON string", + "x-isDateTime": false, + "x-description": [ + "The variable is a JSON string" + ] + }, + "is_sensitive": { + "type": "boolean", + "title": "Is Sensitive", + "description": "The variable is sensitive", + "x-isDateTime": false, + "x-description": [ + "The variable is sensitive" + ] + }, + "visible_build": { + "type": "boolean", + "title": "Visible during build", + "description": "The variable is visible during build", + "x-isDateTime": false, + "x-description": [ + "The variable is visible during build" + ] + }, + "visible_runtime": { + "type": "boolean", + "title": "Visible at runtime", + "description": "The variable is visible at runtime", + "x-isDateTime": false, + "x-description": [ + "The variable is visible at runtime" + ] + }, + "application_scope": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Application Scope", + "description": "Applications that have access to this variable", + "x-isDateTime": false, + "x-description": [ + "Applications that have access to this variable" + ] + } + }, + "additionalProperties": false + }, + "ProxyRoute": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "ProxyRoute Identifier", + "description": "The identifier of ProxyRoute", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The identifier of ProxyRoute" + ] + }, + "primary": { + "type": "boolean", + "nullable": true, + "title": "Is primary", + "description": "This route is the primary route of the environment", + "x-isDateTime": false, + "x-description": [ + "This route is the primary route of the environment" + ] + }, + "production_url": { + "type": "string", + "nullable": true, + "title": "Production URL", + "description": "How this URL route would look on production environment", + "x-isDateTime": false, + "x-description": [ + "How this URL route would look on production environment" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "type": { + "type": "string", + "enum": [ + "proxy", + "redirect", + "upstream" + ], + "title": "Route type", + "description": "Route type.", + "x-isDateTime": false, + "x-description": [ + "Route type." + ] + }, + "tls": { + "type": "object", + "properties": { + "strict_transport_security": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "nullable": true, + "title": "Is enabled", + "description": "Whether strict transport security is enabled or not.", + "x-description": [ + "Whether strict transport security is enabled or not." + ] + }, + "include_subdomains": { + "type": "boolean", + "nullable": true, + "title": "Is subdomains included", + "description": "Whether the strict transport security policy should include all subdomains.", + "x-description": [ + "Whether the strict transport security policy should include all subdomains." + ] + }, + "preload": { + "type": "boolean", + "nullable": true, + "title": "Is strict transport security preloaded", + "description": "Whether the strict transport security policy should be preloaded in browsers.", + "x-description": [ + "Whether the strict transport security policy should be preloaded in browsers." + ] + } + }, + "required": [ + "enabled", + "include_subdomains", + "preload" + ], + "additionalProperties": false, + "title": "Strict-Transport-Security options.", + "description": "" + }, + "min_version": { + "type": "string", + "enum": [ + "TLSv1.0", + "TLSv1.1", + "TLSv1.2", + "TLSv1.3" + ], + "nullable": true, + "title": "Minimum TLS version", + "description": "The minimum TLS version to support.", + "x-description": [ + "The minimum TLS version to support." + ] + }, + "client_authentication": { + "type": "string", + "enum": [ + "request", + "require" + ], + "nullable": true, + "title": "Client authentication", + "description": "The type of client authentication to request.", + "x-description": [ + "The type of client authentication to request." + ] + }, + "client_certificate_authorities": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Client certificate authorities", + "description": "Certificate authorities to validate the client certificate against. If not specified, a default set of trusted CAs will be used.", + "x-description": [ + "Certificate authorities to validate the client certificate against. If not specified, a default set of trusted", + "CAs will be used." + ] + } + }, + "required": [ + "strict_transport_security", + "min_version", + "client_authentication", + "client_certificate_authorities" + ], + "additionalProperties": false, + "title": "TLS settings", + "description": "TLS settings for the route.", + "x-isDateTime": false, + "x-description": [ + "TLS settings for the route." + ] + }, + "to": { + "type": "string", + "title": "Proxy destination", + "description": "", + "x-isDateTime": false + }, + "redirects": { + "type": "object", + "properties": { + "expires": { + "type": "string", + "title": "Expires", + "description": "The amount of time, in seconds, to cache the redirects.", + "x-description": [ + "The amount of time, in seconds, to cache the redirects." + ] + }, + "paths": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "regexp": { + "type": "boolean", + "title": "Is regexp", + "description": "Whether the path is a regular expression." + }, + "to": { + "type": "string", + "title": "Redirect URL", + "description": "The URL to redirect to." + }, + "prefix": { + "type": "boolean", + "nullable": true, + "title": "Is prefix", + "description": "Whether to redirect all the paths that start with the path." + }, + "append_suffix": { + "type": "boolean", + "nullable": true, + "title": "Append suffix", + "description": "Whether to append the incoming suffix to the redirected URL." + }, + "code": { + "type": "integer", + "enum": [ + 301, + 302, + 307, + 308 + ], + "title": "Redirect code", + "description": "The redirect code to use." + }, + "expires": { + "type": "string", + "nullable": true, + "title": "Expires", + "description": "The amount of time, in seconds, to cache the redirects." + } + }, + "required": [ + "regexp", + "to", + "prefix", + "append_suffix", + "code", + "expires" + ], + "additionalProperties": false + }, + "title": "Path", + "description": "The paths to redirect", + "x-description": [ + "The paths to redirect" + ] + } + }, + "required": [ + "expires", + "paths" + ], + "additionalProperties": false, + "title": "Redirect configuration", + "description": "The configuration of the redirects.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The configuration of the redirects." + ] + }, + "cache": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether the cache is enabled.", + "x-description": [ + "Whether the cache is enabled." + ] + }, + "default_ttl": { + "type": "integer", + "title": "Default TTL", + "description": "The TTL to apply when the response doesn't specify one. Only applies to static files.", + "x-description": [ + "The TTL to apply when the response doesn't specify one. Only applies to static files." + ] + }, + "cookies": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Cookies", + "description": "The cookies to take into account for the cache key.", + "x-description": [ + "The cookies to take into account for the cache key." + ] + }, + "headers": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Headers", + "description": "The headers to take into account for the cache key.", + "x-description": [ + "The headers to take into account for the cache key." + ] + } + }, + "required": [ + "enabled", + "default_ttl", + "cookies", + "headers" + ], + "additionalProperties": false, + "title": "Cache configuration", + "description": "Cache configuration.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Cache configuration." + ] + }, + "ssi": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether SSI include is enabled.", + "x-description": [ + "Whether SSI include is enabled." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "SSI configuration", + "description": "Server-Side Include configuration.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Server-Side Include configuration." + ] + }, + "upstream": { + "type": "string", + "title": "Upstream", + "description": "The upstream to use for this route.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The upstream to use for this route." + ] + }, + "sticky": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether sticky routing is enabled.", + "x-description": [ + "Whether sticky routing is enabled." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "Sticky configuration", + "description": "Sticky routing configuration.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Sticky routing configuration." + ] + } + }, + "required": [ + "attributes", + "type", + "tls", + "to" + ], + "additionalProperties": false + }, + "RedirectRoute": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "RedirectRoute Identifier", + "description": "The identifier of RedirectRoute", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The identifier of RedirectRoute" + ] + }, + "primary": { + "type": "boolean", + "nullable": true, + "title": "Is primary", + "description": "This route is the primary route of the environment", + "x-isDateTime": false, + "x-description": [ + "This route is the primary route of the environment" + ] + }, + "production_url": { + "type": "string", + "nullable": true, + "title": "Production URL", + "description": "How this URL route would look on production environment", + "x-isDateTime": false, + "x-description": [ + "How this URL route would look on production environment" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "type": { + "type": "string", + "enum": [ + "proxy", + "redirect", + "upstream" + ], + "title": "Route type", + "description": "Route type.", + "x-isDateTime": false, + "x-description": [ + "Route type." + ] + }, + "tls": { + "type": "object", + "properties": { + "strict_transport_security": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "nullable": true, + "title": "Is enabled", + "description": "Whether strict transport security is enabled or not.", + "x-description": [ + "Whether strict transport security is enabled or not." + ] + }, + "include_subdomains": { + "type": "boolean", + "nullable": true, + "title": "Is subdomains included", + "description": "Whether the strict transport security policy should include all subdomains.", + "x-description": [ + "Whether the strict transport security policy should include all subdomains." + ] + }, + "preload": { + "type": "boolean", + "nullable": true, + "title": "Is strict transport security preloaded", + "description": "Whether the strict transport security policy should be preloaded in browsers.", + "x-description": [ + "Whether the strict transport security policy should be preloaded in browsers." + ] + } + }, + "required": [ + "enabled", + "include_subdomains", + "preload" + ], + "additionalProperties": false, + "title": "Strict-Transport-Security options.", + "description": "" + }, + "min_version": { + "type": "string", + "enum": [ + "TLSv1.0", + "TLSv1.1", + "TLSv1.2", + "TLSv1.3" + ], + "nullable": true, + "title": "Minimum TLS version", + "description": "The minimum TLS version to support.", + "x-description": [ + "The minimum TLS version to support." + ] + }, + "client_authentication": { + "type": "string", + "enum": [ + "request", + "require" + ], + "nullable": true, + "title": "Client authentication", + "description": "The type of client authentication to request.", + "x-description": [ + "The type of client authentication to request." + ] + }, + "client_certificate_authorities": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Client certificate authorities", + "description": "Certificate authorities to validate the client certificate against. If not specified, a default set of trusted CAs will be used.", + "x-description": [ + "Certificate authorities to validate the client certificate against. If not specified, a default set of trusted", + "CAs will be used." + ] + } + }, + "required": [ + "strict_transport_security", + "min_version", + "client_authentication", + "client_certificate_authorities" + ], + "additionalProperties": false, + "title": "TLS settings", + "description": "TLS settings for the route.", + "x-isDateTime": false, + "x-description": [ + "TLS settings for the route." + ] + }, + "to": { + "type": "string", + "title": "Redirect destination", + "description": "", + "x-isDateTime": false + }, + "redirects": { + "type": "object", + "properties": { + "expires": { + "type": "string", + "title": "Expires", + "description": "The amount of time, in seconds, to cache the redirects.", + "x-description": [ + "The amount of time, in seconds, to cache the redirects." + ] + }, + "paths": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "regexp": { + "type": "boolean", + "title": "Is regexp", + "description": "Whether the path is a regular expression." + }, + "to": { + "type": "string", + "title": "Redirect URL", + "description": "The URL to redirect to." + }, + "prefix": { + "type": "boolean", + "nullable": true, + "title": "Is prefix", + "description": "Whether to redirect all the paths that start with the path." + }, + "append_suffix": { + "type": "boolean", + "nullable": true, + "title": "Append suffix", + "description": "Whether to append the incoming suffix to the redirected URL." + }, + "code": { + "type": "integer", + "enum": [ + 301, + 302, + 307, + 308 + ], + "title": "Redirect code", + "description": "The redirect code to use." + }, + "expires": { + "type": "string", + "nullable": true, + "title": "Expires", + "description": "The amount of time, in seconds, to cache the redirects." + } + }, + "required": [ + "regexp", + "to", + "prefix", + "append_suffix", + "code", + "expires" + ], + "additionalProperties": false + }, + "title": "Path", + "description": "The paths to redirect", + "x-description": [ + "The paths to redirect" + ] + } + }, + "required": [ + "expires", + "paths" + ], + "additionalProperties": false, + "title": "Redirect configuration", + "description": "The configuration of the redirects.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The configuration of the redirects." + ] + }, + "cache": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether the cache is enabled.", + "x-description": [ + "Whether the cache is enabled." + ] + }, + "default_ttl": { + "type": "integer", + "title": "Default TTL", + "description": "The TTL to apply when the response doesn't specify one. Only applies to static files.", + "x-description": [ + "The TTL to apply when the response doesn't specify one. Only applies to static files." + ] + }, + "cookies": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Cookies", + "description": "The cookies to take into account for the cache key.", + "x-description": [ + "The cookies to take into account for the cache key." + ] + }, + "headers": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Headers", + "description": "The headers to take into account for the cache key.", + "x-description": [ + "The headers to take into account for the cache key." + ] + } + }, + "required": [ + "enabled", + "default_ttl", + "cookies", + "headers" + ], + "additionalProperties": false, + "title": "Cache configuration", + "description": "Cache configuration.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Cache configuration." + ] + }, + "ssi": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether SSI include is enabled.", + "x-description": [ + "Whether SSI include is enabled." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "SSI configuration", + "description": "Server-Side Include configuration.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Server-Side Include configuration." + ] + }, + "upstream": { + "type": "string", + "title": "Upstream", + "description": "The upstream to use for this route.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The upstream to use for this route." + ] + }, + "sticky": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether sticky routing is enabled.", + "x-description": [ + "Whether sticky routing is enabled." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "Sticky configuration", + "description": "Sticky routing configuration.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Sticky routing configuration." + ] + } + }, + "required": [ + "attributes", + "type", + "tls", + "to" + ], + "additionalProperties": false + }, + "Ref": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Ref Identifier", + "description": "The identifier of Ref", + "x-isDateTime": false, + "x-description": [ + "The identifier of Ref" + ] + }, + "ref": { + "type": "string", + "title": "Name", + "description": "The name of the reference", + "x-isDateTime": false, + "x-description": [ + "The name of the reference" + ] + }, + "object": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Type", + "description": "The type of object pointed to", + "x-description": [ + "The type of object pointed to" + ] + }, + "sha": { + "type": "string", + "title": "The SHA of the object pointed to", + "description": "" + } + }, + "required": [ + "type", + "sha" + ], + "additionalProperties": false, + "title": "Object", + "description": "The object the reference points to", + "x-isDateTime": false, + "x-description": [ + "The object the reference points to" + ] + }, + "sha": { + "type": "string", + "title": "SHA", + "description": "The commit sha of the ref", + "x-isDateTime": false, + "x-description": [ + "The commit sha of the ref" + ] + } + }, + "required": [ + "id", + "ref", + "object", + "sha" + ], + "additionalProperties": false + }, + "RefCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Ref" + } + }, + "ReplacementDomainStorage": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "ReplacementDomainStorage Identifier", + "description": "The identifier of ReplacementDomainStorage", + "x-isDateTime": false, + "x-description": [ + "The identifier of ReplacementDomainStorage" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Type", + "description": "Domain type", + "x-isDateTime": false, + "x-description": [ + "Domain type" + ] + }, + "project": { + "type": "string", + "title": "Project name", + "description": "", + "x-isDateTime": false + }, + "name": { + "type": "string", + "title": "Domain name", + "description": "", + "x-isDateTime": false + }, + "registered_name": { + "type": "string", + "title": "Claimed domain name", + "description": "", + "x-isDateTime": false + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "replacement_for": { + "type": "string", + "title": "Replacement For", + "description": "Prod domain which will be replaced by this domain.", + "x-isDateTime": false, + "x-description": [ + "Prod domain which will be replaced by this domain." + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "name", + "attributes" + ], + "additionalProperties": false + }, + "ReplacementDomainStorageCreateInput": { + "type": "object", + "properties": { + "name": { + "type": "string", + "title": "Domain name", + "description": "", + "x-isDateTime": false + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "replacement_for": { + "type": "string", + "title": "Replacement For", + "description": "Prod domain which will be replaced by this domain.", + "x-isDateTime": false, + "x-description": [ + "Prod domain which will be replaced by this domain." + ] + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "ReplacementDomainStoragePatch": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + } + }, + "additionalProperties": false + }, + "Route": { + "oneOf": [ + { + "$ref": "#/components/schemas/ProxyRoute" + }, + { + "$ref": "#/components/schemas/RedirectRoute" + }, + { + "$ref": "#/components/schemas/UpstreamRoute" + } + ] + }, + "RouteCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Route" + } + }, + "ScriptIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "ScriptIntegration Identifier", + "description": "The identifier of ScriptIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of ScriptIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Events", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to execute the hook on" + ] + }, + "excluded_environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Environments", + "description": "The environments to not execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to not execute the hook on" + ] + }, + "states": { + "type": "array", + "items": { + "type": "string" + }, + "title": "States", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "result": { + "type": "string", + "enum": [ + "*", + "failure", + "success" + ], + "title": "Result", + "description": "Result to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Result to execute the hook on" + ] + }, + "script": { + "type": "string", + "title": "script", + "description": "The script to run", + "x-isDateTime": false, + "x-description": [ + "The script to run" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "events", + "environments", + "excluded_environments", + "states", + "result", + "script" + ], + "additionalProperties": false + }, + "ScriptIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Events", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to execute the hook on" + ] + }, + "excluded_environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Environments", + "description": "The environments to not execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to not execute the hook on" + ] + }, + "states": { + "type": "array", + "items": { + "type": "string" + }, + "title": "States", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "result": { + "type": "string", + "enum": [ + "*", + "failure", + "success" + ], + "title": "Result", + "description": "Result to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Result to execute the hook on" + ] + }, + "script": { + "type": "string", + "title": "script", + "description": "The script to run", + "x-isDateTime": false, + "x-description": [ + "The script to run" + ] + } + }, + "required": [ + "type", + "script" + ], + "additionalProperties": false + }, + "ScriptIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Events", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to execute the hook on" + ] + }, + "excluded_environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Environments", + "description": "The environments to not execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to not execute the hook on" + ] + }, + "states": { + "type": "array", + "items": { + "type": "string" + }, + "title": "States", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "result": { + "type": "string", + "enum": [ + "*", + "failure", + "success" + ], + "title": "Result", + "description": "Result to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Result to execute the hook on" + ] + }, + "script": { + "type": "string", + "title": "script", + "description": "The script to run", + "x-isDateTime": false, + "x-description": [ + "The script to run" + ] + } + }, + "required": [ + "type", + "script" + ], + "additionalProperties": false + }, + "SlackIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "SlackIntegration Identifier", + "description": "The identifier of SlackIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of SlackIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "channel": { + "type": "string", + "title": "Slack Channel", + "description": "The Slack channel to post messages to", + "x-isDateTime": false, + "x-description": [ + "The Slack channel to post messages to" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "channel" + ], + "additionalProperties": false + }, + "SlackIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "token": { + "type": "string", + "title": "Slack Token", + "description": "The Slack token to use", + "x-isDateTime": false, + "x-description": [ + "The Slack token to use" + ] + }, + "channel": { + "type": "string", + "title": "Slack Channel", + "description": "The Slack channel to post messages to", + "x-isDateTime": false, + "x-description": [ + "The Slack channel to post messages to" + ] + } + }, + "required": [ + "type", + "token", + "channel" + ], + "additionalProperties": false + }, + "SlackIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "token": { + "type": "string", + "title": "Slack Token", + "description": "The Slack token to use", + "x-isDateTime": false, + "x-description": [ + "The Slack token to use" + ] + }, + "channel": { + "type": "string", + "title": "Slack Channel", + "description": "The Slack channel to post messages to", + "x-isDateTime": false, + "x-description": [ + "The Slack channel to post messages to" + ] + } + }, + "required": [ + "type", + "token", + "channel" + ], + "additionalProperties": false + }, + "SplunkIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "SplunkIntegration Identifier", + "description": "The identifier of SplunkIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of SplunkIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "URL", + "description": "The Splunk HTTP Event Connector REST API endpoint", + "x-isDateTime": false, + "x-description": [ + "The Splunk HTTP Event Connector REST API endpoint" + ] + }, + "index": { + "type": "string", + "title": "Index", + "description": "The Splunk Index", + "x-isDateTime": false, + "x-description": [ + "The Splunk Index" + ] + }, + "sourcetype": { + "type": "string", + "title": "Sourcetype", + "description": "The event 'sourcetype'", + "x-isDateTime": false, + "x-description": [ + "The event 'sourcetype'" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "extra", + "url", + "index", + "sourcetype", + "tls_verify", + "excluded_services" + ], + "additionalProperties": false + }, + "SplunkIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "URL", + "description": "The Splunk HTTP Event Connector REST API endpoint", + "x-isDateTime": false, + "x-description": [ + "The Splunk HTTP Event Connector REST API endpoint" + ] + }, + "index": { + "type": "string", + "title": "Index", + "description": "The Splunk Index", + "x-isDateTime": false, + "x-description": [ + "The Splunk Index" + ] + }, + "token": { + "type": "string", + "title": "Authorization Token", + "description": "The Splunk Authorization Token", + "x-isDateTime": false, + "x-description": [ + "The Splunk Authorization Token" + ] + }, + "sourcetype": { + "type": "string", + "title": "Sourcetype", + "description": "The event 'sourcetype'", + "x-isDateTime": false, + "x-description": [ + "The event 'sourcetype'" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type", + "url", + "index", + "token" + ], + "additionalProperties": false + }, + "SplunkIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "URL", + "description": "The Splunk HTTP Event Connector REST API endpoint", + "x-isDateTime": false, + "x-description": [ + "The Splunk HTTP Event Connector REST API endpoint" + ] + }, + "index": { + "type": "string", + "title": "Index", + "description": "The Splunk Index", + "x-isDateTime": false, + "x-description": [ + "The Splunk Index" + ] + }, + "token": { + "type": "string", + "title": "Authorization Token", + "description": "The Splunk Authorization Token", + "x-isDateTime": false, + "x-description": [ + "The Splunk Authorization Token" + ] + }, + "sourcetype": { + "type": "string", + "title": "Sourcetype", + "description": "The event 'sourcetype'", + "x-isDateTime": false, + "x-description": [ + "The event 'sourcetype'" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type", + "url", + "index", + "token" + ], + "additionalProperties": false + }, + "SumologicIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "SumologicIntegration Identifier", + "description": "The identifier of SumologicIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of SumologicIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "The Sumologic HTTPS endpoint", + "description": "", + "x-isDateTime": false + }, + "category": { + "type": "string", + "title": "Category", + "description": "The Category used to easy filtering (sent as X-Sumo-Category header)", + "x-isDateTime": false, + "x-description": [ + "The Category used to easy filtering (sent as X-Sumo-Category header)" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "extra", + "url", + "category", + "tls_verify", + "excluded_services" + ], + "additionalProperties": false + }, + "SumologicIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "The Sumologic HTTPS endpoint", + "description": "", + "x-isDateTime": false + }, + "category": { + "type": "string", + "title": "Category", + "description": "The Category used to easy filtering (sent as X-Sumo-Category header)", + "x-isDateTime": false, + "x-description": [ + "The Category used to easy filtering (sent as X-Sumo-Category header)" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "SumologicIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "url": { + "type": "string", + "title": "The Sumologic HTTPS endpoint", + "description": "", + "x-isDateTime": false + }, + "category": { + "type": "string", + "title": "Category", + "description": "The Category used to easy filtering (sent as X-Sumo-Category header)", + "x-isDateTime": false, + "x-description": [ + "The Category used to easy filtering (sent as X-Sumo-Category header)" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "SyslogIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "SyslogIntegration Identifier", + "description": "The identifier of SyslogIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of SyslogIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "host": { + "type": "string", + "title": "Host", + "description": "Syslog relay/collector host", + "x-isDateTime": false, + "x-description": [ + "Syslog relay/collector host" + ] + }, + "port": { + "type": "integer", + "title": "Port", + "description": "Syslog relay/collector port", + "x-isDateTime": false, + "x-description": [ + "Syslog relay/collector port" + ] + }, + "protocol": { + "type": "string", + "enum": [ + "tcp", + "tls", + "udp" + ], + "title": "Protocol", + "description": "Transport protocol", + "x-isDateTime": false, + "x-description": [ + "Transport protocol" + ] + }, + "facility": { + "type": "integer", + "title": "Facility", + "description": "Syslog facility", + "x-isDateTime": false, + "x-description": [ + "Syslog facility" + ] + }, + "message_format": { + "type": "string", + "enum": [ + "rfc3164", + "rfc5424" + ], + "title": "Message format", + "description": "Syslog message format", + "x-isDateTime": false, + "x-description": [ + "Syslog message format" + ] + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "extra", + "host", + "port", + "protocol", + "facility", + "message_format", + "tls_verify", + "excluded_services" + ], + "additionalProperties": false + }, + "SyslogIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "host": { + "type": "string", + "title": "Host", + "description": "Syslog relay/collector host", + "x-isDateTime": false, + "x-description": [ + "Syslog relay/collector host" + ] + }, + "port": { + "type": "integer", + "title": "Port", + "description": "Syslog relay/collector port", + "x-isDateTime": false, + "x-description": [ + "Syslog relay/collector port" + ] + }, + "protocol": { + "type": "string", + "enum": [ + "tcp", + "tls", + "udp" + ], + "title": "Protocol", + "description": "Transport protocol", + "x-isDateTime": false, + "x-description": [ + "Transport protocol" + ] + }, + "facility": { + "type": "integer", + "title": "Facility", + "description": "Syslog facility", + "x-isDateTime": false, + "x-description": [ + "Syslog facility" + ] + }, + "message_format": { + "type": "string", + "enum": [ + "rfc3164", + "rfc5424" + ], + "title": "Message format", + "description": "Syslog message format", + "x-isDateTime": false, + "x-description": [ + "Syslog message format" + ] + }, + "auth_token": { + "type": "string", + "title": "Authentication token", + "description": "", + "x-isDateTime": false + }, + "auth_mode": { + "type": "string", + "enum": [ + "prefix", + "structured_data" + ], + "title": "Authentication mode", + "description": "", + "x-isDateTime": false + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "SyslogIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "extra": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Extra", + "description": "Arbitrary key/value pairs to include with forwarded logs", + "x-isDateTime": false, + "x-description": [ + "Arbitrary key/value pairs to include with forwarded logs" + ] + }, + "host": { + "type": "string", + "title": "Host", + "description": "Syslog relay/collector host", + "x-isDateTime": false, + "x-description": [ + "Syslog relay/collector host" + ] + }, + "port": { + "type": "integer", + "title": "Port", + "description": "Syslog relay/collector port", + "x-isDateTime": false, + "x-description": [ + "Syslog relay/collector port" + ] + }, + "protocol": { + "type": "string", + "enum": [ + "tcp", + "tls", + "udp" + ], + "title": "Protocol", + "description": "Transport protocol", + "x-isDateTime": false, + "x-description": [ + "Transport protocol" + ] + }, + "facility": { + "type": "integer", + "title": "Facility", + "description": "Syslog facility", + "x-isDateTime": false, + "x-description": [ + "Syslog facility" + ] + }, + "message_format": { + "type": "string", + "enum": [ + "rfc3164", + "rfc5424" + ], + "title": "Message format", + "description": "Syslog message format", + "x-isDateTime": false, + "x-description": [ + "Syslog message format" + ] + }, + "auth_token": { + "type": "string", + "title": "Authentication token", + "description": "", + "x-isDateTime": false + }, + "auth_mode": { + "type": "string", + "enum": [ + "prefix", + "structured_data" + ], + "title": "Authentication mode", + "description": "", + "x-isDateTime": false + }, + "tls_verify": { + "type": "boolean", + "title": "TLS Verify", + "description": "Enable/Disable HTTPS certificate verification", + "x-isDateTime": false, + "x-description": [ + "Enable/Disable HTTPS certificate verification" + ] + }, + "excluded_services": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Services", + "description": "Comma separated list of service and application names to exclude from logging", + "x-isDateTime": false, + "x-description": [ + "Comma separated list of service and application names to exclude from logging" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "SystemInformation": { + "type": "object", + "properties": { + "version": { + "type": "string", + "title": "Version", + "description": "The version of this project server", + "x-isDateTime": false, + "x-description": [ + "The version of this project server" + ] + }, + "image": { + "type": "string", + "title": "Image", + "description": "The image version of the project server", + "x-isDateTime": false, + "x-description": [ + "The image version of the project server" + ] + }, + "started_at": { + "type": "string", + "format": "date-time", + "title": "Started At", + "description": "", + "x-isDateTime": true + } + }, + "required": [ + "version", + "image", + "started_at" + ], + "additionalProperties": false + }, + "Tree": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Tree Identifier", + "description": "The identifier of Tree", + "x-isDateTime": false, + "x-description": [ + "The identifier of Tree" + ] + }, + "sha": { + "type": "string", + "title": "SHA", + "description": "The identifier of the tree", + "x-isDateTime": false, + "x-description": [ + "The identifier of the tree" + ] + }, + "tree": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string", + "title": "Item path", + "description": "The path of the item" + }, + "mode": { + "type": "string", + "enum": [ + "040000", + "100644", + "100755", + "120000", + "160000" + ], + "title": "Item mode", + "description": "The mode of the item" + }, + "type": { + "type": "string", + "title": "Item type", + "description": "The type of the item (blob or tree)" + }, + "sha": { + "type": "string", + "nullable": true, + "title": "Item SHA", + "description": "The sha of the item" + } + }, + "required": [ + "path", + "mode", + "type", + "sha" + ], + "additionalProperties": false + }, + "title": "Tree items", + "description": "The tree items", + "x-isDateTime": false, + "x-description": [ + "The tree items" + ] + } + }, + "required": [ + "id", + "sha", + "tree" + ], + "additionalProperties": false + }, + "UpstreamRoute": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "UpstreamRoute Identifier", + "description": "The identifier of UpstreamRoute", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The identifier of UpstreamRoute" + ] + }, + "primary": { + "type": "boolean", + "nullable": true, + "title": "Is primary", + "description": "This route is the primary route of the environment", + "x-isDateTime": false, + "x-description": [ + "This route is the primary route of the environment" + ] + }, + "production_url": { + "type": "string", + "nullable": true, + "title": "Production URL", + "description": "How this URL route would look on production environment", + "x-isDateTime": false, + "x-description": [ + "How this URL route would look on production environment" + ] + }, + "attributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Arbitrary attributes", + "description": "Arbitrary attributes attached to this resource", + "x-isDateTime": false, + "x-description": [ + "Arbitrary attributes attached to this resource" + ] + }, + "type": { + "type": "string", + "enum": [ + "proxy", + "redirect", + "upstream" + ], + "title": "Route type", + "description": "Route type.", + "x-isDateTime": false, + "x-description": [ + "Route type." + ] + }, + "tls": { + "type": "object", + "properties": { + "strict_transport_security": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "nullable": true, + "title": "Is enabled", + "description": "Whether strict transport security is enabled or not.", + "x-description": [ + "Whether strict transport security is enabled or not." + ] + }, + "include_subdomains": { + "type": "boolean", + "nullable": true, + "title": "Is subdomains included", + "description": "Whether the strict transport security policy should include all subdomains.", + "x-description": [ + "Whether the strict transport security policy should include all subdomains." + ] + }, + "preload": { + "type": "boolean", + "nullable": true, + "title": "Is strict transport security preloaded", + "description": "Whether the strict transport security policy should be preloaded in browsers.", + "x-description": [ + "Whether the strict transport security policy should be preloaded in browsers." + ] + } + }, + "required": [ + "enabled", + "include_subdomains", + "preload" + ], + "additionalProperties": false, + "title": "Strict-Transport-Security options.", + "description": "" + }, + "min_version": { + "type": "string", + "enum": [ + "TLSv1.0", + "TLSv1.1", + "TLSv1.2", + "TLSv1.3" + ], + "nullable": true, + "title": "Minimum TLS version", + "description": "The minimum TLS version to support.", + "x-description": [ + "The minimum TLS version to support." + ] + }, + "client_authentication": { + "type": "string", + "enum": [ + "request", + "require" + ], + "nullable": true, + "title": "Client authentication", + "description": "The type of client authentication to request.", + "x-description": [ + "The type of client authentication to request." + ] + }, + "client_certificate_authorities": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Client certificate authorities", + "description": "Certificate authorities to validate the client certificate against. If not specified, a default set of trusted CAs will be used.", + "x-description": [ + "Certificate authorities to validate the client certificate against. If not specified, a default set of trusted", + "CAs will be used." + ] + } + }, + "required": [ + "strict_transport_security", + "min_version", + "client_authentication", + "client_certificate_authorities" + ], + "additionalProperties": false, + "title": "TLS settings", + "description": "TLS settings for the route.", + "x-isDateTime": false, + "x-description": [ + "TLS settings for the route." + ] + }, + "cache": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether the cache is enabled.", + "x-description": [ + "Whether the cache is enabled." + ] + }, + "default_ttl": { + "type": "integer", + "title": "Default TTL", + "description": "The TTL to apply when the response doesn't specify one. Only applies to static files.", + "x-description": [ + "The TTL to apply when the response doesn't specify one. Only applies to static files." + ] + }, + "cookies": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Cookies", + "description": "The cookies to take into account for the cache key.", + "x-description": [ + "The cookies to take into account for the cache key." + ] + }, + "headers": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Headers", + "description": "The headers to take into account for the cache key.", + "x-description": [ + "The headers to take into account for the cache key." + ] + } + }, + "required": [ + "enabled", + "default_ttl", + "cookies", + "headers" + ], + "additionalProperties": false, + "title": "Cache configuration", + "description": "Cache configuration.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Cache configuration." + ] + }, + "ssi": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether SSI include is enabled.", + "x-description": [ + "Whether SSI include is enabled." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "SSI configuration", + "description": "Server-Side Include configuration.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Server-Side Include configuration." + ] + }, + "upstream": { + "type": "string", + "title": "Upstream", + "description": "The upstream to use for this route.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The upstream to use for this route." + ] + }, + "redirects": { + "type": "object", + "properties": { + "expires": { + "type": "string", + "title": "Expires", + "description": "The amount of time, in seconds, to cache the redirects.", + "x-description": [ + "The amount of time, in seconds, to cache the redirects." + ] + }, + "paths": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "regexp": { + "type": "boolean", + "title": "Is regexp", + "description": "Whether the path is a regular expression." + }, + "to": { + "type": "string", + "title": "Redirect URL", + "description": "The URL to redirect to." + }, + "prefix": { + "type": "boolean", + "nullable": true, + "title": "Is prefix", + "description": "Whether to redirect all the paths that start with the path." + }, + "append_suffix": { + "type": "boolean", + "nullable": true, + "title": "Append suffix", + "description": "Whether to append the incoming suffix to the redirected URL." + }, + "code": { + "type": "integer", + "enum": [ + 301, + 302, + 307, + 308 + ], + "title": "Redirect code", + "description": "The redirect code to use." + }, + "expires": { + "type": "string", + "nullable": true, + "title": "Expires", + "description": "The amount of time, in seconds, to cache the redirects." + } + }, + "required": [ + "regexp", + "to", + "prefix", + "append_suffix", + "code", + "expires" + ], + "additionalProperties": false + }, + "title": "Path", + "description": "The paths to redirect", + "x-description": [ + "The paths to redirect" + ] + } + }, + "required": [ + "expires", + "paths" + ], + "additionalProperties": false, + "title": "Redirect configuration", + "description": "The configuration of the redirects.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The configuration of the redirects." + ] + }, + "sticky": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Is enabled", + "description": "Whether sticky routing is enabled.", + "x-description": [ + "Whether sticky routing is enabled." + ] + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "Sticky configuration", + "description": "Sticky routing configuration.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Sticky routing configuration." + ] + }, + "to": { + "type": "string", + "title": "Proxy destination", + "description": "", + "nullable": true, + "x-isDateTime": false + } + }, + "required": [ + "attributes", + "type", + "tls" + ], + "additionalProperties": false + }, + "Version": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Version Identifier", + "description": "The identifier of Version", + "x-isDateTime": false, + "x-description": [ + "The identifier of Version" + ] + }, + "commit": { + "type": "string", + "nullable": true, + "title": "Commit SHA", + "description": "The SHA of the commit of this version", + "x-isDateTime": false, + "x-description": [ + "The SHA of the commit of this version" + ] + }, + "locked": { + "type": "boolean", + "title": "Is locked", + "description": "Whether this version is locked and cannot be modified", + "x-isDateTime": false, + "x-description": [ + "Whether this version is locked and cannot be modified" + ] + }, + "routing": { + "type": "object", + "properties": { + "percentage": { + "type": "integer", + "title": "Traffic percentage", + "description": "The percentage of traffic routed to this version", + "x-description": [ + "The percentage of traffic routed to this version" + ] + } + }, + "required": [ + "percentage" + ], + "additionalProperties": false, + "title": "Routing", + "description": "Configuration about the traffic routed to this version", + "x-isDateTime": false, + "x-description": [ + "Configuration about the traffic routed to this version" + ] + } + }, + "required": [ + "id", + "commit", + "locked", + "routing" + ], + "additionalProperties": false + }, + "VersionCollection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Version" + } + }, + "VersionCreateInput": { + "type": "object", + "properties": { + "routing": { + "type": "object", + "properties": { + "percentage": { + "type": "integer", + "title": "Traffic percentage", + "description": "The percentage of traffic routed to this version", + "x-description": [ + "The percentage of traffic routed to this version" + ] + } + }, + "additionalProperties": false, + "title": "Routing", + "description": "Configuration about the traffic routed to this version", + "x-isDateTime": false, + "x-description": [ + "Configuration about the traffic routed to this version" + ] + } + }, + "additionalProperties": false + }, + "VersionPatch": { + "type": "object", + "properties": { + "routing": { + "type": "object", + "properties": { + "percentage": { + "type": "integer", + "title": "Traffic percentage", + "description": "The percentage of traffic routed to this version", + "x-description": [ + "The percentage of traffic routed to this version" + ] + } + }, + "additionalProperties": false, + "title": "Routing", + "description": "Configuration about the traffic routed to this version", + "x-isDateTime": false, + "x-description": [ + "Configuration about the traffic routed to this version" + ] + } + }, + "additionalProperties": false + }, + "WebHookIntegration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "WebHookIntegration Identifier", + "description": "The identifier of WebHookIntegration", + "x-isDateTime": false, + "x-description": [ + "The identifier of WebHookIntegration" + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Creation date", + "description": "The creation date", + "x-isDateTime": true, + "x-description": [ + "The creation date" + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "title": "Update date", + "description": "The update date", + "x-isDateTime": true, + "x-description": [ + "The update date" + ] + }, + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Events", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to execute the hook on" + ] + }, + "excluded_environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Environments", + "description": "The environments to not execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to not execute the hook on" + ] + }, + "states": { + "type": "array", + "items": { + "type": "string" + }, + "title": "States", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "result": { + "type": "string", + "enum": [ + "*", + "failure", + "success" + ], + "title": "Result", + "description": "Result to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Result to execute the hook on" + ] + }, + "shared_key": { + "type": "string", + "nullable": true, + "title": "Shared Key", + "description": "The JWS shared secret key", + "x-isDateTime": false, + "x-description": [ + "The JWS shared secret key" + ] + }, + "url": { + "type": "string", + "title": "URL", + "description": "The URL of the webhook", + "x-isDateTime": false, + "x-description": [ + "The URL of the webhook" + ] + } + }, + "required": [ + "created_at", + "updated_at", + "type", + "events", + "environments", + "excluded_environments", + "states", + "result", + "shared_key", + "url" + ], + "additionalProperties": false + }, + "WebHookIntegrationCreateInput": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Events", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to execute the hook on" + ] + }, + "excluded_environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Environments", + "description": "The environments to not execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to not execute the hook on" + ] + }, + "states": { + "type": "array", + "items": { + "type": "string" + }, + "title": "States", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "result": { + "type": "string", + "enum": [ + "*", + "failure", + "success" + ], + "title": "Result", + "description": "Result to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Result to execute the hook on" + ] + }, + "shared_key": { + "type": "string", + "nullable": true, + "title": "Shared Key", + "description": "The JWS shared secret key", + "x-isDateTime": false, + "x-description": [ + "The JWS shared secret key" + ] + }, + "url": { + "type": "string", + "title": "URL", + "description": "The URL of the webhook", + "x-isDateTime": false, + "x-description": [ + "The URL of the webhook" + ] + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "WebHookIntegrationPatch": { + "type": "object", + "properties": { + "type": { + "type": "string", + "title": "Integration type", + "description": "", + "x-isDateTime": false + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Events", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Environments", + "description": "The environments to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to execute the hook on" + ] + }, + "excluded_environments": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Excluded Environments", + "description": "The environments to not execute the hook on", + "x-isDateTime": false, + "x-description": [ + "The environments to not execute the hook on" + ] + }, + "states": { + "type": "array", + "items": { + "type": "string" + }, + "title": "States", + "description": "Events to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Events to execute the hook on" + ] + }, + "result": { + "type": "string", + "enum": [ + "*", + "failure", + "success" + ], + "title": "Result", + "description": "Result to execute the hook on", + "x-isDateTime": false, + "x-description": [ + "Result to execute the hook on" + ] + }, + "shared_key": { + "type": "string", + "nullable": true, + "title": "Shared Key", + "description": "The JWS shared secret key", + "x-isDateTime": false, + "x-description": [ + "The JWS shared secret key" + ] + }, + "url": { + "type": "string", + "title": "URL", + "description": "The URL of the webhook", + "x-isDateTime": false, + "x-description": [ + "The URL of the webhook" + ] + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "AutoscalerCPUPressureTrigger": { + "description": "CPU pressure trigger settings.\n\nWhen CPU pressure goes below lower bound, service will be scaled down.\nWhen CPU pressure goes above upper bound, service will be scaled up.", + "properties": { + "enabled": { + "type": "boolean", + "nullable": true, + "title": "Enabled", + "description": "Whether the trigger is enabled", + "x-isDateTime": false, + "x-description": [ + "Whether the trigger is enabled" + ] + }, + "down": { + "allOf": [ + { + "description": "Lower bound on resource usage" + }, + { + "$ref": "#/components/schemas/AutoscalerCondition" + } + ], + "x-isDateTime": false + }, + "up": { + "allOf": [ + { + "description": "Upper bound on resource usage" + }, + { + "$ref": "#/components/schemas/AutoscalerCondition" + } + ], + "x-isDateTime": false + } + }, + "title": "AutoscalerCPUPressureTrigger", + "type": "object", + "x-description": [ + "CPU pressure trigger settings. When CPU pressure goes below lower bound, service will be scaled down. When CPU", + "pressure goes above upper bound, service will be scaled up." + ] + }, + "AutoscalerCPUResources": { + "description": "CPU scaling settings", + "properties": { + "min": { + "description": "Minimum CPUs when scaling down vertically", + "minimum": 0, + "title": "Min", + "type": "number", + "x-isDateTime": false, + "x-description": [ + "Minimum CPUs when scaling down vertically" + ] + }, + "max": { + "description": "Maximum CPUs when scaling up vertically", + "minimum": 0, + "title": "Max", + "type": "number", + "x-isDateTime": false, + "x-description": [ + "Maximum CPUs when scaling up vertically" + ] + } + }, + "title": "AutoscalerCPUResources", + "type": "object", + "x-description": [ + "CPU scaling settings" + ] + }, + "AutoscalerCPUTrigger": { + "description": "CPU resource trigger settings.\n\nWhen CPU usage goes below lower bound, service will be scaled down.\nWhen CPU usage goes above upper bound, service will be scaled up.", + "properties": { + "enabled": { + "type": "boolean", + "nullable": true, + "title": "Enabled", + "description": "Whether the trigger is enabled", + "x-isDateTime": false, + "x-description": [ + "Whether the trigger is enabled" + ] + }, + "down": { + "allOf": [ + { + "description": "Lower bound on resource usage" + }, + { + "$ref": "#/components/schemas/AutoscalerCondition" + } + ], + "x-isDateTime": false + }, + "up": { + "allOf": [ + { + "description": "Upper bound on resource usage" + }, + { + "$ref": "#/components/schemas/AutoscalerCondition" + } + ], + "x-isDateTime": false + } + }, + "title": "AutoscalerCPUTrigger", + "type": "object", + "x-description": [ + "CPU resource trigger settings. When CPU usage goes below lower bound, service will be scaled down. When CPU usage", + "goes above upper bound, service will be scaled up." + ] + }, + "AutoscalerCondition": { + "description": "Trigger condition settings", + "properties": { + "threshold": { + "description": "Value at which the condition is satisfied", + "maximum": 100, + "minimum": 0, + "title": "Threshold", + "type": "number", + "x-isDateTime": false, + "x-description": [ + "Value at which the condition is satisfied" + ] + }, + "duration": { + "allOf": [ + { + "description": "Number of seconds during which the condition must be satisfied" + }, + { + "$ref": "#/components/schemas/AutoscalerDuration" + } + ], + "x-isDateTime": false + }, + "enabled": { + "type": "boolean", + "nullable": true, + "title": "Enabled", + "description": "Whether the condition should be used for generating alerts", + "x-isDateTime": false, + "x-description": [ + "Whether the condition should be used for generating alerts" + ] + } + }, + "required": [ + "threshold" + ], + "title": "AutoscalerCondition", + "type": "object", + "x-description": [ + "Trigger condition settings" + ] + }, + "AutoscalerDuration": { + "enum": [ + 60, + 120, + 300, + 600, + 1800, + 3600 + ], + "title": "AutoscalerDuration", + "type": "integer" + }, + "AutoscalerInstances": { + "description": "Horizontal scaling settings", + "properties": { + "min": { + "description": "Minimum number of instances when scaling down horizontally", + "title": "Min", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "Minimum number of instances when scaling down horizontally" + ] + }, + "max": { + "description": "Maximum number of instances when scaling up horizontally", + "title": "Max", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "Maximum number of instances when scaling up horizontally" + ] + } + }, + "title": "AutoscalerInstances", + "type": "object", + "x-description": [ + "Horizontal scaling settings" + ] + }, + "AutoscalerMemoryPressureTrigger": { + "description": "Memory pressure trigger settings.\n\nWhen memory pressure goes below lower bound, service will be scaled down.\nWhen memory pressure goes above upper bound, service will be scaled up.", + "properties": { + "enabled": { + "type": "boolean", + "nullable": true, + "title": "Enabled", + "description": "Whether the trigger is enabled", + "x-isDateTime": false, + "x-description": [ + "Whether the trigger is enabled" + ] + }, + "down": { + "allOf": [ + { + "description": "Lower bound on resource usage" + }, + { + "$ref": "#/components/schemas/AutoscalerCondition" + } + ], + "x-isDateTime": false + }, + "up": { + "allOf": [ + { + "description": "Upper bound on resource usage" + }, + { + "$ref": "#/components/schemas/AutoscalerCondition" + } + ], + "x-isDateTime": false + } + }, + "title": "AutoscalerMemoryPressureTrigger", + "type": "object", + "x-description": [ + "Memory pressure trigger settings. When memory pressure goes below lower bound, service will be scaled down. When", + "memory pressure goes above upper bound, service will be scaled up." + ] + }, + "AutoscalerMemoryResources": { + "description": "Memory scaling settings", + "properties": { + "min": { + "description": "Minimum memory (bytes) when scaling down vertically", + "minimum": 0, + "title": "Min", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "Minimum memory (bytes) when scaling down vertically" + ] + }, + "max": { + "description": "Maximum memory (bytes) when scaling up vertically", + "minimum": 0, + "title": "Max", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "Maximum memory (bytes) when scaling up vertically" + ] + } + }, + "title": "AutoscalerMemoryResources", + "type": "object", + "x-description": [ + "Memory scaling settings" + ] + }, + "AutoscalerMemoryTrigger": { + "description": "Memory resource trigger settings.\n\nWhen memory usage goes below lower bound, service will be scaled down.\nWhen memory usage goes above upper bound, service will be scaled up.", + "properties": { + "enabled": { + "type": "boolean", + "nullable": true, + "title": "Enabled", + "description": "Whether the trigger is enabled", + "x-isDateTime": false, + "x-description": [ + "Whether the trigger is enabled" + ] + }, + "down": { + "allOf": [ + { + "description": "Lower bound on resource usage" + }, + { + "$ref": "#/components/schemas/AutoscalerCondition" + } + ], + "x-isDateTime": false + }, + "up": { + "allOf": [ + { + "description": "Upper bound on resource usage" + }, + { + "$ref": "#/components/schemas/AutoscalerCondition" + } + ], + "x-isDateTime": false + } + }, + "title": "AutoscalerMemoryTrigger", + "type": "object", + "x-description": [ + "Memory resource trigger settings. When memory usage goes below lower bound, service will be scaled down. When", + "memory usage goes above upper bound, service will be scaled up." + ] + }, + "AutoscalerResources": { + "description": "Vertical scaling settings", + "properties": { + "cpu": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AutoscalerCPUResources" + }, + "nullable": true, + "description": "Lower/Upper bounds on CPU allocation when scaling", + "x-isDateTime": false, + "x-description": [ + "Lower/Upper bounds on CPU allocation when scaling" + ] + }, + "memory": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AutoscalerMemoryResources" + }, + "nullable": true, + "description": "Lower/Upper bounds on Memory allocation when scaling", + "x-isDateTime": false, + "x-description": [ + "Lower/Upper bounds on Memory allocation when scaling" + ] + } + }, + "title": "AutoscalerResources", + "type": "object", + "x-description": [ + "Vertical scaling settings" + ] + }, + "AutoscalerScalingCooldown": { + "description": "Scaling cooldown settings", + "properties": { + "up": { + "description": "Number of seconds to wait until scaling up can be done again (since last attempt)", + "minimum": 0, + "title": "Up", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "Number of seconds to wait until scaling up can be done again (since last attempt)" + ] + }, + "down": { + "description": "Number of seconds to wait until scaling down can be done again (since last attempt)", + "minimum": 0, + "title": "Down", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "Number of seconds to wait until scaling down can be done again (since last attempt)" + ] + } + }, + "title": "AutoscalerScalingCooldown", + "type": "object", + "x-description": [ + "Scaling cooldown settings" + ] + }, + "AutoscalerScalingFactor": { + "description": "Scaling factor settings", + "properties": { + "up": { + "description": "Number of instances to add when scaling up horizontally", + "minimum": 0, + "title": "Up", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "Number of instances to add when scaling up horizontally" + ] + }, + "down": { + "description": "Number of instances to remove when scaling down horizontally", + "minimum": 0, + "title": "Down", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "Number of instances to remove when scaling down horizontally" + ] + } + }, + "title": "AutoscalerScalingFactor", + "type": "object", + "x-description": [ + "Scaling factor settings" + ] + }, + "AutoscalerServiceSettings": { + "description": "Autoscaling settings for a specific service", + "properties": { + "triggers": { + "allOf": [ + { + "description": "Metrics should be evaluated as triggers for autoscaling" + }, + { + "$ref": "#/components/schemas/AutoscalerTriggers" + } + ], + "x-isDateTime": false + }, + "instances": { + "allOf": [ + { + "description": "Lower/Upper bounds on number of instances for horizontal scaling" + }, + { + "$ref": "#/components/schemas/AutoscalerInstances" + } + ], + "x-isDateTime": false + }, + "resources": { + "allOf": [ + { + "description": "Lower/Upper bounds on cpu/memory for vertical scaling" + }, + { + "$ref": "#/components/schemas/AutoscalerResources" + } + ], + "x-isDateTime": false + }, + "scale_factor": { + "allOf": [ + { + "description": "How many instances to add/remove on each scaling attempt" + }, + { + "$ref": "#/components/schemas/AutoscalerScalingFactor" + } + ], + "x-isDateTime": false + }, + "scale_cooldown": { + "allOf": [ + { + "description": "How long to wait before the next scaling attempt can be performed" + }, + { + "$ref": "#/components/schemas/AutoscalerScalingCooldown" + } + ], + "x-isDateTime": false + } + }, + "title": "AutoscalerServiceSettings", + "type": "object", + "x-description": [ + "Autoscaling settings for a specific service" + ] + }, + "AutoscalerSettings": { + "description": "Update model for autoscaling settings.\n\nThis model is mainly used for partial updates (PATCH), therefore all its\nattributes are optional.", + "properties": { + "services": { + "additionalProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AutoscalerServiceSettings" + }, + "nullable": true + }, + "type": "object", + "nullable": true, + "title": "Services", + "description": "Each service for which autoscaling is configured is listed in the key", + "x-isDateTime": false, + "x-description": [ + "Each service for which autoscaling is configured is listed in the key" + ] + } + }, + "title": "AutoscalerSettings", + "type": "object", + "x-description": [ + "Update model for autoscaling settings. This model is mainly used for partial updates (PATCH), therefore all its", + "attributes are optional." + ] + }, + "AutoscalerTriggers": { + "additionalProperties": false, + "description": "Scaling triggers settings", + "properties": { + "cpu": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AutoscalerCPUTrigger" + }, + "nullable": true, + "description": "Settings for scaling based on CPU usage", + "x-isDateTime": false, + "x-description": [ + "Settings for scaling based on CPU usage" + ] + }, + "memory": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AutoscalerMemoryTrigger" + }, + "nullable": true, + "description": "Settings for scaling based on Memory usage", + "x-isDateTime": false, + "x-description": [ + "Settings for scaling based on Memory usage" + ] + }, + "cpu_pressure": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AutoscalerCPUPressureTrigger" + }, + "nullable": true, + "description": "Settings for scaling based on CPU pressure", + "x-isDateTime": false, + "x-description": [ + "Settings for scaling based on CPU pressure" + ] + }, + "memory_pressure": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AutoscalerMemoryPressureTrigger" + }, + "nullable": true, + "description": "Settings for scaling based on Memory pressure", + "x-isDateTime": false, + "x-description": [ + "Settings for scaling based on Memory pressure" + ] + } + }, + "title": "AutoscalerTriggers", + "type": "object", + "x-description": [ + "Scaling triggers settings" + ] + }, + "Invoice": { + "type": "object", + "description": "The invoice object.", + "properties": { + "id": { + "type": "string", + "description": "The invoice id.", + "x-isDateTime": false, + "x-description": [ + "The invoice id." + ] + }, + "invoice_number": { + "description": "The invoice number.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The invoice number." + ] + }, + "type": { + "description": "Invoice type.", + "type": "string", + "enum": [ + "invoice", + "credit_memo" + ], + "x-isDateTime": false, + "x-description": [ + "Invoice type." + ] + }, + "order_id": { + "description": "The id of the related order.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The id of the related order." + ] + }, + "related_invoice_id": { + "description": "If the invoice is a credit memo (type=credit_memo), this field stores the id of the related/original invoice.", + "type": "string", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "If the invoice is a credit memo (type=credit_memo), this field stores the id of the related/original invoice." + ] + }, + "status": { + "description": "The invoice status.", + "type": "string", + "enum": [ + "paid", + "charged_off", + "pending", + "refunded", + "canceled", + "refund_pending" + ], + "x-isDateTime": false, + "x-description": [ + "The invoice status." + ] + }, + "owner": { + "description": "The ULID of the owner.", + "type": "string", + "format": "ulid", + "x-isDateTime": false, + "x-description": [ + "The ULID of the owner." + ] + }, + "invoice_date": { + "description": "The invoice date.", + "type": "string", + "format": "date-time", + "nullable": true, + "x-isDateTime": true, + "x-description": [ + "The invoice date." + ] + }, + "invoice_due": { + "description": "The invoice due date.", + "type": "string", + "format": "date-time", + "nullable": true, + "x-isDateTime": true, + "x-description": [ + "The invoice due date." + ] + }, + "created": { + "description": "The time when the invoice was created.", + "type": "string", + "format": "date-time", + "nullable": true, + "x-isDateTime": true, + "x-description": [ + "The time when the invoice was created." + ] + }, + "changed": { + "description": "The time when the invoice was changed.", + "type": "string", + "format": "date-time", + "nullable": true, + "x-isDateTime": true, + "x-description": [ + "The time when the invoice was changed." + ] + }, + "company": { + "description": "Company name (if any).", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "Company name (if any)." + ] + }, + "total": { + "description": "The invoice total.", + "type": "number", + "format": "double", + "x-isDateTime": false, + "x-description": [ + "The invoice total." + ] + }, + "address": { + "$ref": "#/components/schemas/Address" + }, + "notes": { + "description": "The invoice note.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The invoice note." + ] + }, + "invoice_pdf": { + "$ref": "#/components/schemas/InvoicePDF" + } + }, + "x-description": [ + "The invoice object." + ] + }, + "Organization": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "ulid", + "description": "The ID of the organization.", + "x-isDateTime": false, + "x-description": [ + "The ID of the organization." + ] + }, + "type": { + "type": "string", + "description": "The type of the organization.", + "enum": [ + "fixed", + "flexible" + ], + "x-isDateTime": false, + "x-description": [ + "The type of the organization." + ] + }, + "owner_id": { + "type": "string", + "format": "uuid", + "description": "The ID of the owner.", + "x-isDateTime": false, + "x-description": [ + "The ID of the owner." + ] + }, + "namespace": { + "type": "string", + "description": "The namespace in which the organization name is unique.", + "x-isDateTime": false, + "x-description": [ + "The namespace in which the organization name is unique." + ] + }, + "name": { + "type": "string", + "description": "A unique machine name representing the organization.", + "x-isDateTime": false, + "x-description": [ + "A unique machine name representing the organization." + ] + }, + "label": { + "type": "string", + "description": "The human-readable label of the organization.", + "x-isDateTime": false, + "x-description": [ + "The human-readable label of the organization." + ] + }, + "country": { + "type": "string", + "description": "The organization country (2-letter country code).", + "maxLength": 2, + "x-isDateTime": false, + "x-description": [ + "The organization country (2-letter country code)." + ] + }, + "capabilities": { + "type": "array", + "description": "The organization capabilities.", + "items": { + "type": "string" + }, + "uniqueItems": true, + "x-isDateTime": false, + "x-description": [ + "The organization capabilities." + ] + }, + "vendor": { + "type": "string", + "description": "The vendor.", + "x-isDateTime": false, + "x-description": [ + "The vendor." + ] + }, + "billing_profile_id": { + "type": "string", + "description": "The Billing Profile ID.", + "x-isDateTime": false, + "x-description": [ + "The Billing Profile ID." + ] + }, + "billing_legacy": { + "type": "boolean", + "description": "Whether the account is billed with the legacy system.", + "x-isDateTime": false, + "x-description": [ + "Whether the account is billed with the legacy system." + ] + }, + "security_contact": { + "type": "string", + "format": "email", + "description": "The security contact email address for the organization.", + "x-isDateTime": false, + "x-description": [ + "The security contact email address for the organization." + ] + }, + "status": { + "type": "string", + "description": "The status of the organization.", + "enum": [ + "active", + "restricted", + "suspended", + "deleted" + ], + "x-isDateTime": false, + "x-description": [ + "The status of the organization." + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the organization was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the organization was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the organization was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the organization was last updated." + ] + }, + "_links": { + "type": "object", + "properties": { + "self": { + "type": "object", + "description": "Link to the current organization.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current organization." + ] + }, + "update": { + "type": "object", + "description": "Link for updating the current organization.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for updating the current organization." + ] + }, + "delete": { + "type": "object", + "description": "Link for deleting the current organization.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for deleting the current organization." + ] + }, + "members": { + "type": "object", + "description": "Link to the current organization's members.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current organization's members." + ] + }, + "create-member": { + "type": "object", + "description": "Link for creating a new organization member.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for creating a new organization member." + ] + }, + "address": { + "type": "object", + "description": "Link to the current organization's address.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current organization's address." + ] + }, + "profile": { + "type": "object", + "description": "Link to the current organization's profile.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current organization's profile." + ] + }, + "payment-source": { + "type": "object", + "description": "Link to the current organization's payment source.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current organization's payment source." + ] + }, + "orders": { + "type": "object", + "description": "Link to the current organization's orders.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current organization's orders." + ] + }, + "vouchers": { + "type": "object", + "description": "Link to the current organization's vouchers.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current organization's vouchers." + ] + }, + "apply-voucher": { + "type": "object", + "description": "Link for applying a voucher for the current organization.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for applying a voucher for the current organization." + ] + }, + "subscriptions": { + "type": "object", + "description": "Link to the current organization's subscriptions.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current organization's subscriptions." + ] + }, + "create-subscription": { + "type": "object", + "description": "Link for creating a new organization subscription.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for creating a new organization subscription." + ] + }, + "estimate-subscription": { + "type": "object", + "description": "Link for estimating the price of a new subscription.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link for estimating the price of a new subscription." + ] + }, + "mfa-enforcement": { + "type": "object", + "description": "Link to the current organization's MFA enforcement settings.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current organization's MFA enforcement settings." + ] + } + } + } + } + }, + "OrganizationReference": { + "description": "The referenced organization, or null if it no longer exists.", + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string", + "format": "ulid", + "description": "The ID of the organization.", + "x-isDateTime": false, + "x-description": [ + "The ID of the organization." + ] + }, + "type": { + "type": "string", + "description": "The type of the organization.", + "x-isDateTime": false, + "x-description": [ + "The type of the organization." + ] + }, + "owner_id": { + "type": "string", + "format": "uuid", + "description": "The ID of the owner.", + "x-isDateTime": false, + "x-description": [ + "The ID of the owner." + ] + }, + "name": { + "type": "string", + "description": "A unique machine name representing the organization.", + "x-isDateTime": false, + "x-description": [ + "A unique machine name representing the organization." + ] + }, + "label": { + "type": "string", + "description": "The human-readable label of the organization.", + "x-isDateTime": false, + "x-description": [ + "The human-readable label of the organization." + ] + }, + "vendor": { + "type": "string", + "description": "The vendor.", + "x-isDateTime": false, + "x-description": [ + "The vendor." + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the organization was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the organization was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the organization was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the organization was last updated." + ] + } + }, + "x-description": [ + "The referenced organization, or null if it no longer exists." + ] + }, + "OrganizationMember": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of the user.", + "deprecated": true, + "x-isDateTime": false, + "x-description": [ + "The ID of the user." + ] + }, + "organization_id": { + "type": "string", + "format": "ulid", + "description": "The ID of the organization.", + "x-isDateTime": false, + "x-description": [ + "The ID of the organization." + ] + }, + "user_id": { + "type": "string", + "format": "uuid", + "description": "The ID of the user.", + "x-isDateTime": false, + "x-description": [ + "The ID of the user." + ] + }, + "permissions": { + "$ref": "#/components/schemas/Permissions" + }, + "level": { + "type": "string", + "description": "Access level of the member.", + "enum": [ + "admin", + "viewer" + ], + "x-isDateTime": false, + "x-description": [ + "Access level of the member." + ] + }, + "owner": { + "type": "boolean", + "description": "Whether the member is the organization owner.", + "x-isDateTime": false, + "x-description": [ + "Whether the member is the organization owner." + ] + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the member was created.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the member was created." + ] + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time when the member was last updated.", + "x-isDateTime": true, + "x-description": [ + "The date and time when the member was last updated." + ] + }, + "_links": { + "type": "object", + "properties": { + "self": { + "type": "object", + "description": "Link to the current member.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current member." + ] + }, + "update": { + "type": "object", + "description": "Link for updating the current member.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for updating the current member." + ] + }, + "delete": { + "type": "object", + "description": "Link for deleting the current member.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for deleting the current member." + ] + } + } + } + } + }, + "Vouchers": { + "type": "object", + "properties": { + "uuid": { + "type": "string", + "format": "uuid", + "description": "The uuid of the user.", + "x-isDateTime": false, + "x-description": [ + "The uuid of the user." + ] + }, + "vouchers_total": { + "type": "string", + "description": "The total voucher credit given to the user.", + "x-isDateTime": false, + "x-description": [ + "The total voucher credit given to the user." + ] + }, + "vouchers_applied": { + "type": "string", + "description": "The part of total voucher credit applied to orders.", + "x-isDateTime": false, + "x-description": [ + "The part of total voucher credit applied to orders." + ] + }, + "vouchers_remaining_balance": { + "type": "string", + "description": "The remaining voucher credit, available for future orders.", + "x-isDateTime": false, + "x-description": [ + "The remaining voucher credit, available for future orders." + ] + }, + "currency": { + "type": "string", + "description": "The currency of the vouchers.", + "x-isDateTime": false, + "x-description": [ + "The currency of the vouchers." + ] + }, + "vouchers": { + "description": "Array of vouchers.", + "type": "array", + "items": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "The voucher code." + }, + "amount": { + "type": "string", + "description": "The total voucher credit." + }, + "currency": { + "type": "string", + "description": "The currency of the voucher." + }, + "orders": { + "type": "array", + "description": "Array of orders to which a voucher applied.", + "items": { + "type": "object", + "properties": { + "order_id": { + "type": "string", + "description": "The id of the order." + }, + "status": { + "type": "string", + "description": "The status of the order." + }, + "billing_period_start": { + "type": "string", + "description": "The billing period start timestamp of the order (ISO 8601)." + }, + "billing_period_end": { + "type": "string", + "description": "The billing period end timestamp of the order (ISO 8601)." + }, + "order_total": { + "type": "string", + "description": "The total of the order." + }, + "order_discount": { + "type": "string", + "description": "The total voucher credit applied to the order." + }, + "currency": { + "type": "string", + "description": "The currency of the order." + } + } + } + } + } + }, + "x-isDateTime": false, + "x-description": [ + "Array of vouchers." + ] + }, + "_links": { + "type": "object", + "properties": { + "self": { + "type": "object", + "description": "Link to the current resource.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current resource." + ] + } + } + } + } + }, + "Permissions": { + "type": "array", + "description": "The organization member permissions.", + "items": { + "type": "string", + "enum": [ + "admin", + "billing", + "members", + "plans", + "projects:create", + "projects:list" + ] + }, + "x-description": [ + "The organization member permissions." + ] + }, + "EstimationObject": { + "type": "object", + "description": "A price estimate object.", + "properties": { + "plan": { + "type": "string", + "description": "The monthly price of the plan.", + "x-isDateTime": false, + "x-description": [ + "The monthly price of the plan." + ] + }, + "user_licenses": { + "type": "string", + "description": "The monthly price of the user licenses.", + "x-isDateTime": false, + "x-description": [ + "The monthly price of the user licenses." + ] + }, + "environments": { + "type": "string", + "description": "The monthly price of the environments.", + "x-isDateTime": false, + "x-description": [ + "The monthly price of the environments." + ] + }, + "storage": { + "type": "string", + "description": "The monthly price of the storage.", + "x-isDateTime": false, + "x-description": [ + "The monthly price of the storage." + ] + }, + "total": { + "type": "string", + "description": "The total monthly price.", + "x-isDateTime": false, + "x-description": [ + "The total monthly price." + ] + }, + "options": { + "type": "object", + "description": "The unit prices of the options.", + "x-isDateTime": false, + "x-description": [ + "The unit prices of the options." + ] + } + }, + "x-description": [ + "A price estimate object." + ] + }, + "OrganizationEstimationObject": { + "type": "object", + "description": "An estimation of all organization spend.", + "properties": { + "total": { + "type": "string", + "description": "The total estimated price for the organization.", + "x-isDateTime": false, + "x-description": [ + "The total estimated price for the organization." + ] + }, + "sub_total": { + "type": "string", + "description": "The sub total for all projects and sellables.", + "x-isDateTime": false, + "x-description": [ + "The sub total for all projects and sellables." + ] + }, + "vouchers": { + "type": "string", + "description": "The total amount of vouchers.", + "x-isDateTime": false, + "x-description": [ + "The total amount of vouchers." + ] + }, + "user_licenses": { + "type": "object", + "description": "An estimation of user licenses cost.", + "properties": { + "base": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "The number of base user licenses.", + "x-description": [ + "The number of base user licenses." + ] + }, + "total": { + "type": "string", + "description": "The total price for base user licenses.", + "x-description": [ + "The total price for base user licenses." + ] + }, + "list": { + "type": "object", + "properties": { + "admin_user": { + "type": "object", + "description": "An estimation of admin users cost.", + "properties": { + "count": { + "type": "integer", + "description": "The number of admin user licenses.", + "x-description": [ + "The number of admin user licenses." + ] + }, + "total": { + "type": "string", + "description": "The total price for admin user licenses.", + "x-description": [ + "The total price for admin user licenses." + ] + } + }, + "x-description": [ + "An estimation of admin users cost." + ] + }, + "viewer_user": { + "type": "object", + "description": "An estimation of viewer users cost.", + "properties": { + "count": { + "type": "integer", + "description": "The number of viewer user licenses.", + "x-description": [ + "The number of viewer user licenses." + ] + }, + "total": { + "type": "string", + "description": "The total price for viewer user licenses.", + "x-description": [ + "The total price for viewer user licenses." + ] + } + }, + "x-description": [ + "An estimation of viewer users cost." + ] + } + } + } + } + }, + "user_management": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "The number of user_management licenses.", + "x-description": [ + "The number of user_management licenses." + ] + }, + "total": { + "type": "string", + "description": "The total price for user_management licenses.", + "x-description": [ + "The total price for user_management licenses." + ] + }, + "list": { + "type": "object", + "properties": { + "standard_management_user": { + "type": "object", + "description": "An estimation of standard_management_user cost.", + "properties": { + "count": { + "type": "integer", + "description": "The number of standard_management_user licenses.", + "x-description": [ + "The number of standard_management_user licenses." + ] + }, + "total": { + "type": "string", + "description": "The total price for standard_management_user licenses.", + "x-description": [ + "The total price for standard_management_user licenses." + ] + } + }, + "x-description": [ + "An estimation of standard_management_user cost." + ] + }, + "advanced_management_user": { + "type": "object", + "description": "An estimation of advanced_management_user cost.", + "properties": { + "count": { + "type": "integer", + "description": "The number of advanced_management_user licenses.", + "x-description": [ + "The number of advanced_management_user licenses." + ] + }, + "total": { + "type": "string", + "description": "The total price for advanced_management_user licenses.", + "x-description": [ + "The total price for advanced_management_user licenses." + ] + } + }, + "x-description": [ + "An estimation of advanced_management_user cost." + ] + } + } + } + } + } + }, + "x-isDateTime": false, + "x-description": [ + "An estimation of user licenses cost." + ] + }, + "user_management": { + "type": "string", + "description": "An estimation of the advanced user management sellable cost.", + "x-isDateTime": false, + "x-description": [ + "An estimation of the advanced user management sellable cost." + ] + }, + "support_level": { + "type": "string", + "description": "The total monthly price for premium support.", + "x-isDateTime": false, + "x-description": [ + "The total monthly price for premium support." + ] + }, + "subscriptions": { + "type": "object", + "description": "An estimation of subscriptions cost.", + "properties": { + "total": { + "type": "string", + "description": "The total price for subscriptions.", + "x-description": [ + "The total price for subscriptions." + ] + }, + "list": { + "type": "array", + "description": "The list of active subscriptions.", + "items": { + "description": "Details of a subscription", + "type": "object", + "properties": { + "license_id": { + "type": "string", + "description": "The id of the subscription." + }, + "project_title": { + "type": "string", + "description": "The name of the project." + }, + "total": { + "type": "string", + "description": "The total price for the subscription." + }, + "usage": { + "type": "object", + "description": "The detail of the usage for the subscription.", + "properties": { + "cpu": { + "type": "number", + "description": "The total cpu for this subsciption." + }, + "memory": { + "type": "number", + "description": "The total memory for this subsciption." + }, + "storage": { + "type": "number", + "description": "The total storage for this subsciption." + }, + "environments": { + "type": "integer", + "description": "The total environments for this subsciption." + } + } + } + } + }, + "x-description": [ + "The list of active subscriptions." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "An estimation of subscriptions cost." + ] + } + }, + "x-description": [ + "An estimation of all organization spend." + ] + }, + "OrganizationAddonsObject": { + "type": "object", + "description": "The list of available and current add-ons of an organization.", + "properties": { + "available": { + "type": "object", + "description": "The list of available add-ons and their possible values.", + "properties": { + "user_management": { + "type": "object", + "description": "Information about the levels of user management that are available.", + "additionalProperties": { + "type": "number", + "description": "The number of commitment days required for the addon." + }, + "x-description": [ + "Information about the levels of user management that are available." + ] + }, + "support_level": { + "type": "object", + "description": "Information about the levels of support available.", + "additionalProperties": { + "type": "number", + "description": "The number of commitment days required for the addon." + }, + "x-description": [ + "Information about the levels of support available." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "The list of available add-ons and their possible values." + ] + }, + "current": { + "type": "object", + "description": "The list of existing add-ons and their current values.", + "properties": { + "user_management": { + "type": "object", + "description": "Information about the type of user management currently selected.", + "additionalProperties": { + "type": "number", + "description": "The number of commitment days that remain for the addon." + }, + "x-description": [ + "Information about the type of user management currently selected." + ] + }, + "support_level": { + "type": "object", + "description": "Information about the level of support currently selected.", + "additionalProperties": { + "type": "number", + "description": "The number of commitment days that remain for the addon." + }, + "x-description": [ + "Information about the level of support currently selected." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "The list of existing add-ons and their current values." + ] + }, + "upgrades_available": { + "type": "object", + "description": "The upgrades available for current add-ons.", + "properties": { + "user_management": { + "type": "array", + "description": "Available upgrade options for user management.", + "items": { + "type": "string" + }, + "x-description": [ + "Available upgrade options for user management." + ] + }, + "support_level": { + "type": "array", + "description": "Available upgrade options for support.", + "items": { + "type": "string" + }, + "x-description": [ + "Available upgrade options for support." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "The upgrades available for current add-ons." + ] + } + }, + "x-description": [ + "The list of available and current add-ons of an organization." + ] + }, + "SubscriptionAddonsObject": { + "type": "object", + "description": "The list of available and current addons for the license.", + "properties": { + "available": { + "type": "object", + "description": "The list of available addons.", + "properties": { + "continuous_profiling": { + "type": "object", + "description": "Information about the continuous profiling options available.", + "additionalProperties": { + "type": "number", + "description": "The number of commitment days for the addon." + }, + "x-description": [ + "Information about the continuous profiling options available." + ] + }, + "project_support_level": { + "type": "object", + "description": "Information about the project uptime options available.", + "additionalProperties": { + "type": "number", + "description": "The number of commitment days for the addon." + }, + "x-description": [ + "Information about the project uptime options available." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "The list of available addons." + ] + }, + "current": { + "type": "object", + "description": "The list of existing addons and their current values.", + "properties": { + "continuous_profiling": { + "type": "object", + "description": "The current continuous profiling level of the license.", + "additionalProperties": { + "type": "number", + "description": "The number of remaining commitment days for the addon." + }, + "x-description": [ + "The current continuous profiling level of the license." + ] + }, + "project_support_level": { + "type": "object", + "description": "The current project uptime level of the license.", + "additionalProperties": { + "type": "number", + "description": "The number of remaining commitment days for the addon." + }, + "x-description": [ + "The current project uptime level of the license." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "The list of existing addons and their current values." + ] + }, + "upgrades_available": { + "type": "object", + "description": "The upgrades available for current addons.", + "properties": { + "continuous_profiling": { + "type": "array", + "description": "Available upgrade options for continuous profiling.", + "items": { + "type": "string" + }, + "x-description": [ + "Available upgrade options for continuous profiling." + ] + }, + "project_support_level": { + "type": "array", + "description": "Available upgrade options for project uptime.", + "items": { + "type": "string" + }, + "x-description": [ + "Available upgrade options for project uptime." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "The upgrades available for current addons." + ] + } + }, + "x-description": [ + "The list of available and current addons for the license." + ] + }, + "OrganizationAlertConfig": { + "type": "object", + "description": "The alert configuration for an organization.", + "properties": { + "id": { + "type": "string", + "description": "Type of alert (e.g. \"billing\")", + "x-isDateTime": false, + "x-description": [ + "Type of alert (e.g. \"billing\")" + ] + }, + "active": { + "type": "boolean", + "description": "Whether the billing alert should be active or not.", + "x-isDateTime": false, + "x-description": [ + "Whether the billing alert should be active or not." + ] + }, + "alerts_sent": { + "type": "number", + "description": "Number of alerts sent.", + "x-isDateTime": false, + "x-description": [ + "Number of alerts sent." + ] + }, + "last_alert_at": { + "type": "string", + "description": "The datetime the alert was last sent.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The datetime the alert was last sent." + ] + }, + "updated_at": { + "type": "string", + "description": "The datetime the alert was last updated.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The datetime the alert was last updated." + ] + }, + "config": { + "type": "object", + "nullable": true, + "description": "Configuration for threshold and mode.", + "properties": { + "threshold": { + "type": "object", + "description": "Data regarding threshold spend.", + "properties": { + "formatted": { + "type": "string", + "description": "Formatted threshold value.", + "x-description": [ + "Formatted threshold value." + ] + }, + "amount": { + "type": "number", + "description": "Threshold value.", + "x-description": [ + "Threshold value." + ] + }, + "currency_code": { + "type": "string", + "description": "Threshold currency code.", + "x-description": [ + "Threshold currency code." + ] + }, + "currency_symbol": { + "type": "string", + "description": "Threshold currency symbol.", + "x-description": [ + "Threshold currency symbol." + ] + } + }, + "x-description": [ + "Data regarding threshold spend." + ] + }, + "mode": { + "type": "string", + "description": "The mode of alert.", + "x-description": [ + "The mode of alert." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "Configuration for threshold and mode." + ] + } + }, + "x-description": [ + "The alert configuration for an organization." + ] + }, + "UsageAlert": { + "type": "object", + "description": "The usage alert for a subscription.", + "properties": { + "id": { + "type": "string", + "description": "Tidentifier of the alert.", + "x-isDateTime": false, + "x-description": [ + "Tidentifier of the alert." + ] + }, + "active": { + "type": "boolean", + "description": "Whether the usage alert is activated.", + "x-isDateTime": false, + "x-description": [ + "Whether the usage alert is activated." + ] + }, + "alerts_sent": { + "type": "number", + "description": "Number of alerts sent.", + "x-isDateTime": false, + "x-description": [ + "Number of alerts sent." + ] + }, + "last_alert_at": { + "type": "string", + "description": "The datetime the alert was last sent.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The datetime the alert was last sent." + ] + }, + "updated_at": { + "type": "string", + "description": "The datetime the alert was last updated.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The datetime the alert was last updated." + ] + }, + "config": { + "type": "object", + "nullable": true, + "description": "Configuration for the usage alert.", + "properties": { + "threshold": { + "type": "object", + "description": "Data regarding threshold spend.", + "properties": { + "formatted": { + "type": "string", + "description": "Formatted threshold value.", + "x-description": [ + "Formatted threshold value." + ] + }, + "amount": { + "type": "number", + "description": "Threshold value.", + "x-description": [ + "Threshold value." + ] + }, + "unit": { + "type": "string", + "description": "Threshold unit.", + "x-description": [ + "Threshold unit." + ] + } + }, + "x-description": [ + "Data regarding threshold spend." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "Configuration for the usage alert." + ] + } + }, + "x-description": [ + "The usage alert for a subscription." + ] + }, + "PrepaymentObject": { + "type": "object", + "description": "Prepayment information for an organization.", + "properties": { + "prepayment": { + "type": "object", + "description": "Prepayment information for an organization.", + "properties": { + "organization_id": { + "type": "string", + "description": "Organization ID", + "x-description": [ + "Organization ID" + ] + }, + "balance": { + "type": "object", + "description": "The prepayment balance in complex format.", + "properties": { + "formatted": { + "type": "string", + "description": "Formatted balance.", + "x-description": [ + "Formatted balance." + ] + }, + "amount": { + "type": "number", + "description": "The balance amount.", + "x-description": [ + "The balance amount." + ] + }, + "currency_code": { + "type": "string", + "description": "The balance currency code.", + "x-description": [ + "The balance currency code." + ] + }, + "currency_symbol": { + "type": "string", + "description": "The balance currency symbol.", + "x-description": [ + "The balance currency symbol." + ] + } + }, + "x-description": [ + "The prepayment balance in complex format." + ] + }, + "last_updated_at": { + "type": "string", + "nullable": true, + "description": "The date the prepayment balance was last updated.", + "x-description": [ + "The date the prepayment balance was last updated." + ] + }, + "sufficient": { + "type": "boolean", + "description": "Whether the prepayment balance is enough to cover the upcoming order.", + "x-description": [ + "Whether the prepayment balance is enough to cover the upcoming order." + ] + }, + "fallback": { + "type": "string", + "nullable": true, + "description": "The fallback payment method, if any, to be used in case prepayment balance is not enough to cover an order.", + "x-description": [ + "The fallback payment method, if any, to be used in case prepayment balance is not enough to cover an order." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "Prepayment information for an organization." + ] + } + }, + "x-description": [ + "Prepayment information for an organization." + ] + }, + "PrepaymentTransactionObject": { + "type": "object", + "description": "Prepayment transaction for an organization.", + "properties": { + "order_id": { + "type": "string", + "description": "Order ID", + "x-isDateTime": false, + "x-description": [ + "Order ID" + ] + }, + "message": { + "type": "string", + "description": "The message associated with transaction.", + "x-isDateTime": false, + "x-description": [ + "The message associated with transaction." + ] + }, + "status": { + "type": "string", + "description": "Whether the transactions was successful or a failure.", + "x-isDateTime": false, + "x-description": [ + "Whether the transactions was successful or a failure." + ] + }, + "amount": { + "type": "object", + "description": "The prepayment balance in complex format.", + "properties": { + "formatted": { + "type": "string", + "description": "Formatted balance.", + "x-description": [ + "Formatted balance." + ] + }, + "amount": { + "type": "number", + "description": "The balance amount.", + "x-description": [ + "The balance amount." + ] + }, + "currency_code": { + "type": "string", + "description": "The balance currency code.", + "x-description": [ + "The balance currency code." + ] + }, + "currency_symbol": { + "type": "string", + "description": "The balance currency symbol.", + "x-description": [ + "The balance currency symbol." + ] + } + }, + "x-isDateTime": false, + "x-description": [ + "The prepayment balance in complex format." + ] + }, + "created": { + "type": "string", + "description": "Time the transaction was created.", + "x-isDateTime": false, + "x-description": [ + "Time the transaction was created." + ] + }, + "updated": { + "type": "string", + "description": "Time the transaction was last updated.", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Time the transaction was last updated." + ] + }, + "expire_date": { + "type": "string", + "description": "The expiration date of the transaction (deposits only).", + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "The expiration date of the transaction (deposits only)." + ] + } + }, + "x-description": [ + "Prepayment transaction for an organization." + ] + }, + "ArrayFilter": { + "type": "object", + "properties": { + "eq": { + "type": "string", + "description": "Equal", + "x-isDateTime": false, + "x-description": [ + "Equal" + ] + }, + "ne": { + "type": "string", + "description": "Not equal", + "x-isDateTime": false, + "x-description": [ + "Not equal" + ] + }, + "in": { + "type": "string", + "description": "In (comma-separated list)", + "x-isDateTime": false, + "x-description": [ + "In (comma-separated list)" + ] + }, + "nin": { + "type": "string", + "description": "Not in (comma-separated list)", + "x-isDateTime": false, + "x-description": [ + "Not in (comma-separated list)" + ] + } + } + }, + "OrganizationProject": { + "type": "object", + "properties": { + "id": { + "$ref": "#/components/schemas/ProjectID" + }, + "organization_id": { + "$ref": "#/components/schemas/OrganizationID" + }, + "subscription_id": { + "$ref": "#/components/schemas/SubscriptionID" + }, + "vendor": { + "type": "string", + "description": "Vendor of the project.", + "x-isDateTime": false, + "x-description": [ + "Vendor of the project." + ] + }, + "region": { + "$ref": "#/components/schemas/RegionID" + }, + "title": { + "$ref": "#/components/schemas/ProjectTitle" + }, + "type": { + "$ref": "#/components/schemas/ProjectType" + }, + "plan": { + "$ref": "#/components/schemas/ProjectPlan" + }, + "timezone": { + "$ref": "#/components/schemas/ProjectTimeZone" + }, + "default_branch": { + "$ref": "#/components/schemas/ProjectDefaultBranch" + }, + "status": { + "$ref": "#/components/schemas/ProjectStatus" + }, + "trial_plan": { + "$ref": "#/components/schemas/ProjectTrialPlan" + }, + "project_ui": { + "$ref": "#/components/schemas/ProjectUI" + }, + "created_at": { + "$ref": "#/components/schemas/CreatedAt" + }, + "updated_at": { + "$ref": "#/components/schemas/UpdatedAt" + }, + "activities": { + "description": "Activities information for the project.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Activity" + }, + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Activities information for the project." + ] + }, + "project_options": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ProjectOptionsAggregated" + } + ], + "nullable": true, + "x-isDateTime": false + }, + "_links": { + "type": "object", + "properties": { + "self": { + "type": "object", + "description": "Link to the current project.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current project." + ] + }, + "api": { + "type": "object", + "nullable": true, + "description": "Link to the regional API endpoint. Only present if user has project-level access.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the regional API endpoint. Only present if user has project-level access." + ] + }, + "subscription": { + "type": "object", + "nullable": true, + "description": "Link to the subscription. Only present if project has a subscription.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the subscription. Only present if project has a subscription." + ] + }, + "view_usage_alerts": { + "type": "object", + "nullable": true, + "description": "Link to view usage alerts. Only present if user has view permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to view usage alerts. Only present if user has view permission." + ] + }, + "update": { + "type": "object", + "nullable": true, + "description": "Link for updating the current project. Only present if user has update permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for updating the current project. Only present if user has update permission." + ] + }, + "plan_uri": { + "type": "object", + "nullable": true, + "description": "Link to the billing plan page. Only present if user has manage permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the billing plan page. Only present if user has manage permission." + ] + }, + "delete": { + "type": "object", + "nullable": true, + "description": "Link for deleting the current project. Only present if user has delete permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for deleting the current project. Only present if user has delete permission." + ] + }, + "update_usage_alerts": { + "type": "object", + "nullable": true, + "description": "Link to update usage alerts. Only present if user has billing permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link to update usage alerts. Only present if user has billing permission." + ] + }, + "activities": { + "type": "object", + "nullable": true, + "description": "Link to the project's activities. Only present if user has view permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the project's activities. Only present if user has view permission." + ] + }, + "addons": { + "type": "object", + "nullable": true, + "description": "Link to the project's add-ons. Only present if user has view permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the project's add-ons. Only present if user has view permission." + ] + } + } + } + }, + "additionalProperties": false + }, + "OrganizationCarbon": { + "type": "object", + "properties": { + "organization_id": { + "$ref": "#/components/schemas/OrganizationID" + }, + "meta": { + "$ref": "#/components/schemas/MetricsMetadata" + }, + "projects": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrganizationProjectCarbon" + }, + "x-isDateTime": false + }, + "total": { + "$ref": "#/components/schemas/CarbonTotal" + } + }, + "additionalProperties": false + }, + "ProjectAddon": { + "description": "Project add-on. Uses discriminator on `type` to select field shape.", + "allOf": [ + { + "$ref": "#/components/schemas/ProjectAddonBase" + }, + { + "oneOf": [ + { + "$ref": "#/components/schemas/ProjectAddonWithSkuFields" + }, + { + "$ref": "#/components/schemas/ProjectAddonWithQuantityFields" + } + ] + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "backups": "#/components/schemas/ProjectAddonWithSkuFields", + "big_dev": "#/components/schemas/ProjectAddonWithSkuFields", + "big_dev_service": "#/components/schemas/ProjectAddonWithSkuFields", + "blackfire": "#/components/schemas/ProjectAddonWithSkuFields", + "continuous_profiling": "#/components/schemas/ProjectAddonWithSkuFields", + "project_support_level": "#/components/schemas/ProjectAddonWithSkuFields", + "observability_suite": "#/components/schemas/ProjectAddonWithSkuFields", + "user_licenses": "#/components/schemas/ProjectAddonWithQuantityFields", + "hipaa": "#/components/schemas/ProjectAddonWithSkuFields", + "environments": "#/components/schemas/ProjectAddonWithQuantityFields", + "storage": "#/components/schemas/ProjectAddonWithQuantityFields" + } + }, + "x-description": [ + "Project add-on. Uses discriminator on `type` to select field shape." + ], + "x-uniqueDiscriminatorModels": [ + "ProjectAddonWithSkuFields", + "ProjectAddonWithQuantityFields" + ] + }, + "ProjectAddonBase": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/ProjectAddonID" + }, + "project_id": { + "$ref": "#/components/schemas/ProjectID" + }, + "type": { + "$ref": "#/components/schemas/AddonType" + }, + "status": { + "type": "string", + "description": "Lifecycle status of the add-on.", + "enum": [ + "requested", + "active", + "failed" + ], + "x-isDateTime": false, + "x-description": [ + "Lifecycle status of the add-on." + ] + }, + "title": { + "type": "string", + "description": "Human-friendly title of the add-on or SKU.", + "x-isDateTime": false, + "x-description": [ + "Human-friendly title of the add-on or SKU." + ] + }, + "unit": { + "type": "string", + "nullable": true, + "description": "Unit for quantity-based add-ons when applicable.", + "x-isDateTime": false, + "x-description": [ + "Unit for quantity-based add-ons when applicable." + ] + }, + "allowed_values": { + "description": "Allowed values for the add-on depending on user role and options.", + "type": "array", + "nullable": true, + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "x-isDateTime": false, + "x-description": [ + "Allowed values for the add-on depending on user role and options." + ] + }, + "created_at": { + "$ref": "#/components/schemas/CreatedAt" + }, + "updated_at": { + "$ref": "#/components/schemas/UpdatedAt" + }, + "activities": { + "description": "Activities related to the add-on.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Activity" + }, + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Activities related to the add-on." + ] + }, + "_links": { + "type": "object", + "properties": { + "self": { + "type": "object", + "description": "Link to the current add-on.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current add-on." + ] + }, + "update": { + "type": "object", + "nullable": true, + "description": "Link for updating the current add-on.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for updating the current add-on." + ] + }, + "delete": { + "type": "object", + "nullable": true, + "description": "Link for deleting the current add-on.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for deleting the current add-on." + ] + } + } + } + } + }, + "ProjectAddonWithSkuFields": { + "type": "object", + "required": [ + "sku" + ], + "properties": { + "sku": { + "$ref": "#/components/schemas/ProjectAddonSKU" + } + } + }, + "ProjectAddonWithQuantityFields": { + "type": "object", + "required": [ + "quantity" + ], + "properties": { + "quantity": { + "$ref": "#/components/schemas/ProjectAddonQuantity" + } + } + }, + "ProjectCarbon": { + "type": "object", + "properties": { + "project_id": { + "$ref": "#/components/schemas/ProjectID" + }, + "project_title": { + "$ref": "#/components/schemas/ProjectTitle" + }, + "meta": { + "$ref": "#/components/schemas/MetricsMetadata" + }, + "values": { + "$ref": "#/components/schemas/MetricsValues" + }, + "total": { + "$ref": "#/components/schemas/CarbonTotal" + } + }, + "additionalProperties": false + }, + "OrganizationProjectCarbon": { + "type": "object", + "properties": { + "project_id": { + "$ref": "#/components/schemas/ProjectID" + }, + "project_title": { + "$ref": "#/components/schemas/ProjectTitle" + }, + "values": { + "$ref": "#/components/schemas/MetricsValues" + } + }, + "additionalProperties": false + }, + "ProjectOptionsAggregated": { + "type": "object", + "properties": { + "billing": { + "type": "object", + "nullable": true, + "x-isDateTime": false + }, + "defaults": { + "type": "object", + "nullable": true, + "x-isDateTime": false + }, + "enforced": { + "type": "object", + "nullable": true, + "x-isDateTime": false + }, + "initialize": { + "type": "object", + "nullable": true, + "x-isDateTime": false + }, + "plans": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "x-isDateTime": false + }, + "regions": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "x-isDateTime": false + }, + "plan_titles": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/PlanTitles" + } + ], + "nullable": true, + "x-isDateTime": false + }, + "sellables": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/AggregatedSellables" + } + ], + "nullable": true, + "x-isDateTime": false + }, + "features": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/AggregatedFeatures" + } + ], + "nullable": true, + "x-isDateTime": false + }, + "container_sizes": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "description": "Container sizes configuration.", + "x-isDateTime": false, + "x-description": [ + "Container sizes configuration." + ] + }, + "debug": { + "type": "object", + "nullable": true, + "description": "Debug configuration.", + "x-isDateTime": false, + "x-description": [ + "Debug configuration." + ] + } + }, + "additionalProperties": false + }, + "ProjectPlan": { + "type": "string", + "description": "The project plan.", + "x-description": [ + "The project plan." + ] + }, + "ProjectReference": { + "description": "The referenced project, or null if it no longer exists.", + "type": "object", + "nullable": true, + "required": [ + "id", + "organization_id", + "subscription_id", + "region", + "title", + "type", + "plan", + "status", + "created_at", + "updated_at" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/ProjectID" + }, + "organization_id": { + "$ref": "#/components/schemas/OrganizationID" + }, + "subscription_id": { + "$ref": "#/components/schemas/SubscriptionID" + }, + "region": { + "$ref": "#/components/schemas/RegionID" + }, + "title": { + "$ref": "#/components/schemas/ProjectTitle" + }, + "type": { + "$ref": "#/components/schemas/ProjectType" + }, + "plan": { + "$ref": "#/components/schemas/ProjectPlan" + }, + "status": { + "$ref": "#/components/schemas/ProjectStatus" + }, + "created_at": { + "$ref": "#/components/schemas/CreatedAt" + }, + "updated_at": { + "$ref": "#/components/schemas/UpdatedAt" + }, + "invoiced": { + "type": "boolean", + "description": "Whether the project is invoiced.", + "x-isDateTime": false, + "x-description": [ + "Whether the project is invoiced." + ] + } + }, + "additionalProperties": false, + "x-description": [ + "The referenced project, or null if it no longer exists." + ] + }, + "RegionReference": { + "description": "The referenced region, or null if it no longer exists.", + "type": "object", + "nullable": true, + "required": [ + "id", + "label", + "zone", + "selection_label", + "project_label", + "timezone", + "available", + "endpoint", + "provider", + "datacenter", + "compliance", + "created_at", + "updated_at" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/RegionID" + }, + "label": { + "$ref": "#/components/schemas/RegionLabel" + }, + "zone": { + "$ref": "#/components/schemas/RegionZone" + }, + "selection_label": { + "$ref": "#/components/schemas/RegionSelectionLabel" + }, + "project_label": { + "$ref": "#/components/schemas/RegionProjectLabel" + }, + "timezone": { + "$ref": "#/components/schemas/RegionTimezone" + }, + "available": { + "$ref": "#/components/schemas/RegionAvailable" + }, + "private": { + "$ref": "#/components/schemas/RegionPrivate" + }, + "endpoint": { + "$ref": "#/components/schemas/RegionEndpoint" + }, + "provider": { + "$ref": "#/components/schemas/RegionProvider" + }, + "datacenter": { + "$ref": "#/components/schemas/RegionDatacenter" + }, + "envimpact": { + "$ref": "#/components/schemas/RegionEnvImpact" + }, + "compliance": { + "$ref": "#/components/schemas/RegionCompliance" + }, + "created_at": { + "$ref": "#/components/schemas/CreatedAt" + }, + "updated_at": { + "$ref": "#/components/schemas/UpdatedAt" + }, + "environmental_impact": { + "type": "object", + "description": "Environmental impact information for the region.", + "x-isDateTime": false, + "x-description": [ + "Environmental impact information for the region." + ] + } + }, + "additionalProperties": false, + "x-description": [ + "The referenced region, or null if it no longer exists." + ] + }, + "AddonType": { + "type": "string", + "description": "The type of the add-on.", + "x-description": [ + "The type of the add-on." + ] + }, + "ProjectAddonID": { + "type": "string", + "description": "The ID of the add-on.", + "x-description": [ + "The ID of the add-on." + ] + }, + "ProjectAddonSKU": { + "type": "string", + "description": "The SKU of the add-on.", + "x-description": [ + "The SKU of the add-on." + ] + }, + "ProjectAddonQuantity": { + "type": "integer", + "description": "The quantity of the add-on.", + "x-description": [ + "The quantity of the add-on." + ] + }, + "ProjectID": { + "type": "string", + "description": "The ID of the project.", + "x-description": [ + "The ID of the project." + ] + }, + "OrganizationID": { + "type": "string", + "description": "The ID of the organization.", + "x-description": [ + "The ID of the organization." + ] + }, + "SubscriptionID": { + "type": "string", + "description": "The ID of the subscription.", + "x-description": [ + "The ID of the subscription." + ] + }, + "RegionID": { + "type": "string", + "description": "The machine name of the region where the project is located.", + "x-description": [ + "The machine name of the region where the project is located." + ] + }, + "ProjectTitle": { + "type": "string", + "description": "The title of the project.", + "x-description": [ + "The title of the project." + ] + }, + "ProjectType": { + "type": "string", + "description": "The type of projects.", + "enum": [ + "grid", + "dedicated" + ], + "x-description": [ + "The type of projects." + ] + }, + "ProjectTimeZone": { + "type": "string", + "description": "Timezone of the project.", + "x-description": [ + "Timezone of the project." + ] + }, + "ProjectDefaultBranch": { + "type": "string", + "description": "Default branch.", + "x-description": [ + "Default branch." + ] + }, + "ProjectStatus": { + "type": "string", + "description": "The status of the project.", + "enum": [ + "requested", + "active", + "failed", + "suspended", + "deleted" + ], + "x-description": [ + "The status of the project." + ] + }, + "ProjectUI": { + "description": "The URL for the project's user interface.", + "type": "string", + "x-description": [ + "The URL for the project's user interface." + ] + }, + "ProjectTrialPlan": { + "description": "Whether the project is currently on a trial plan.", + "type": "boolean", + "x-description": [ + "Whether the project is currently on a trial plan." + ] + }, + "PlanTitles": { + "type": "object", + "description": "Map of plan IDs to their human-readable titles.", + "additionalProperties": { + "type": "string" + }, + "x-description": [ + "Map of plan IDs to their human-readable titles." + ] + }, + "AggregatedSellables": { + "type": "object", + "description": "Map of sellable names to their configuration.", + "additionalProperties": { + "type": "object", + "description": "Sellable product configuration." + }, + "x-description": [ + "Map of sellable names to their configuration." + ] + }, + "AggregatedFeatures": { + "type": "object", + "properties": { + "backups": { + "type": "object", + "nullable": true, + "description": "Backup features configuration.", + "x-isDateTime": false, + "x-description": [ + "Backup features configuration." + ] + } + } + }, + "RegionLabel": { + "type": "string", + "description": "The human-readable name of the region.", + "x-description": [ + "The human-readable name of the region." + ] + }, + "RegionZone": { + "type": "string", + "description": "The geographical zone of the region.", + "x-description": [ + "The geographical zone of the region." + ] + }, + "RegionSelectionLabel": { + "type": "string", + "description": "The label to display when choosing between regions for new projects.", + "x-description": [ + "The label to display when choosing between regions for new projects." + ] + }, + "RegionProjectLabel": { + "type": "string", + "description": "The label to display on existing projects.", + "x-description": [ + "The label to display on existing projects." + ] + }, + "RegionTimezone": { + "type": "string", + "description": "Default timezone of the region.", + "x-description": [ + "Default timezone of the region." + ] + }, + "RegionAvailable": { + "type": "boolean", + "description": "Indicator whether or not this region is selectable during the checkout. Not available regions will never show up during checkout.", + "x-description": [ + "Indicator whether or not this region is selectable during the checkout. Not available regions will never show up", + "during checkout." + ] + }, + "RegionPrivate": { + "type": "boolean", + "description": "Indicator whether or not this platform is for private use only.", + "x-description": [ + "Indicator whether or not this platform is for private use only." + ] + }, + "RegionEndpoint": { + "type": "string", + "description": "Link to the region API endpoint.", + "x-description": [ + "Link to the region API endpoint." + ] + }, + "RegionProvider": { + "type": "object", + "description": "Information about the region provider.", + "properties": { + "name": { + "type": "string", + "description": "The name of the cloud provider.", + "x-isDateTime": false, + "x-description": [ + "The name of the cloud provider." + ] + }, + "logo": { + "type": "string", + "description": "The logo of the cloud provider (base64 encoded SVG).", + "x-isDateTime": false, + "x-description": [ + "The logo of the cloud provider (base64 encoded SVG)." + ] + } + }, + "additionalProperties": false, + "x-description": [ + "Information about the region provider." + ] + }, + "RegionDatacenter": { + "type": "object", + "description": "Information about the region provider data center.", + "properties": { + "name": { + "type": "string", + "description": "The name/identifier of the data center.", + "x-isDateTime": false, + "x-description": [ + "The name/identifier of the data center." + ] + }, + "label": { + "type": "string", + "description": "The human-readable label of the data center.", + "x-isDateTime": false, + "x-description": [ + "The human-readable label of the data center." + ] + }, + "location": { + "type": "string", + "description": "The physical location of the data center.", + "x-isDateTime": false, + "x-description": [ + "The physical location of the data center." + ] + } + }, + "additionalProperties": false, + "x-description": [ + "Information about the region provider data center." + ] + }, + "RegionEnvImpact": { + "type": "object", + "description": "Information about the region provider's environmental impact.", + "properties": { + "zone": { + "type": "string", + "description": "The geographical zone code for carbon intensity.", + "x-isDateTime": false, + "x-description": [ + "The geographical zone code for carbon intensity." + ] + }, + "carbon_intensity": { + "type": "number", + "description": "The carbon intensity value.", + "x-isDateTime": false, + "x-description": [ + "The carbon intensity value." + ] + }, + "green": { + "type": "boolean", + "description": "Indicator whether the data center uses green energy.", + "x-isDateTime": false, + "x-description": [ + "Indicator whether the data center uses green energy." + ] + } + }, + "additionalProperties": false, + "x-description": [ + "Information about the region provider's environmental impact." + ] + }, + "RegionCompliance": { + "type": "object", + "description": "Information about the region's compliance.", + "properties": { + "hipaa": { + "type": "boolean", + "description": "Indicator whether or not this region is HIPAA compliant.", + "x-isDateTime": false, + "x-description": [ + "Indicator whether or not this region is HIPAA compliant." + ] + } + }, + "additionalProperties": false, + "x-description": [ + "Information about the region's compliance." + ] + }, + "MetricsMetadata": { + "type": "object", + "properties": { + "from": { + "description": "The value used to calculate the lower bound of the temporal query. Inclusive.", + "x-isDateTime": false, + "x-description": [ + "The value used to calculate the lower bound of the temporal query. Inclusive." + ] + }, + "to": { + "description": "The truncated value used to calculate the upper bound of the temporal query. Exclusive.", + "x-isDateTime": false, + "x-description": [ + "The truncated value used to calculate the upper bound of the temporal query. Exclusive." + ] + }, + "interval": { + "description": "The interval used to group the metric values.", + "x-isDateTime": false, + "x-description": [ + "The interval used to group the metric values." + ] + }, + "units": { + "description": "The units associated with the provided values.", + "x-isDateTime": false, + "x-description": [ + "The units associated with the provided values." + ] + } + }, + "additionalProperties": false + }, + "MetricsValues": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MetricsValue" + } + }, + "MetricsValue": { + "type": "object", + "properties": { + "value": { + "description": "The measured value of the metric for the given time interval.", + "x-isDateTime": false, + "x-description": [ + "The measured value of the metric for the given time interval." + ] + }, + "start_time": { + "description": "The timestamp at which the time interval began.", + "x-isDateTime": false, + "x-description": [ + "The timestamp at which the time interval began." + ] + } + }, + "additionalProperties": false + }, + "CarbonTotal": { + "type": "number", + "description": "The calculated total of the metric for the given interval.", + "x-description": [ + "The calculated total of the metric for the given interval." + ] + }, + "CreatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time when the resource was created.", + "x-description": [ + "The date and time when the resource was created." + ] + }, + "UpdatedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time when the resource was last updated.", + "x-description": [ + "The date and time when the resource was last updated." + ] + }, + "GrantedAt": { + "type": "string", + "format": "date-time", + "description": "The date and time when the access was granted.", + "x-description": [ + "The date and time when the access was granted." + ] + }, + "TeamProjectAccess": { + "type": "object", + "properties": { + "team_id": { + "type": "string", + "format": "ulid", + "description": "The ID of the team.", + "x-isDateTime": false, + "x-description": [ + "The ID of the team." + ] + }, + "organization_id": { + "type": "string", + "format": "ulid", + "description": "The ID of the organization.", + "x-isDateTime": false, + "x-description": [ + "The ID of the organization." + ] + }, + "project_id": { + "type": "string", + "description": "The ID of the project.", + "x-isDateTime": false, + "x-description": [ + "The ID of the project." + ] + }, + "project_title": { + "type": "string", + "description": "The title of the project.", + "x-isDateTime": false, + "x-description": [ + "The title of the project." + ] + }, + "granted_at": { + "$ref": "#/components/schemas/GrantedAt" + }, + "updated_at": { + "$ref": "#/components/schemas/UpdatedAt" + }, + "_links": { + "type": "object", + "properties": { + "self": { + "type": "object", + "description": "Link to the current access item.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current access item." + ] + }, + "update": { + "type": "object", + "nullable": true, + "description": "Link for updating the current access item. Only present if user has update permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for updating the current access item. Only present if user has update permission." + ] + }, + "delete": { + "type": "object", + "nullable": true, + "description": "Link for deleting the current access item. Only present if user has delete permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for deleting the current access item. Only present if user has delete permission." + ] + } + } + } + }, + "additionalProperties": false + }, + "UserProjectAccess": { + "type": "object", + "properties": { + "user_id": { + "type": "string", + "format": "uuid", + "description": "The ID of the user.", + "x-isDateTime": false, + "x-description": [ + "The ID of the user." + ] + }, + "organization_id": { + "type": "string", + "format": "ulid", + "description": "The ID of the organization.", + "x-isDateTime": false, + "x-description": [ + "The ID of the organization." + ] + }, + "project_id": { + "type": "string", + "description": "The ID of the project.", + "x-isDateTime": false, + "x-description": [ + "The ID of the project." + ] + }, + "project_title": { + "type": "string", + "description": "The title of the project.", + "x-isDateTime": false, + "x-description": [ + "The title of the project." + ] + }, + "permissions": { + "$ref": "#/components/schemas/ProjectPermissions" + }, + "granted_at": { + "$ref": "#/components/schemas/GrantedAt" + }, + "updated_at": { + "$ref": "#/components/schemas/UpdatedAt" + }, + "_links": { + "type": "object", + "properties": { + "self": { + "type": "object", + "description": "Link to the current access item.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + } + }, + "x-description": [ + "Link to the current access item." + ] + }, + "update": { + "type": "object", + "nullable": true, + "description": "Link for updating the current access item. Only present if user has update permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for updating the current access item. Only present if user has update permission." + ] + }, + "delete": { + "type": "object", + "nullable": true, + "description": "Link for deleting the current access item. Only present if user has delete permission.", + "properties": { + "href": { + "type": "string", + "description": "URL of the link.", + "x-description": [ + "URL of the link." + ] + }, + "method": { + "type": "string", + "description": "The HTTP method to use.", + "x-description": [ + "The HTTP method to use." + ] + } + }, + "x-description": [ + "Link for deleting the current access item. Only present if user has delete permission." + ] + } + } + } + }, + "additionalProperties": false + }, + "ProjectPermissions": { + "type": "array", + "description": "An array of project permissions.", + "items": { + "type": "string", + "enum": [ + "admin", + "viewer", + "development:admin", + "development:contributor", + "development:viewer", + "staging:admin", + "staging:contributor", + "staging:viewer", + "production:admin", + "production:contributor", + "production:viewer" + ] + }, + "x-description": [ + "An array of project permissions." + ] + }, + "ProjectFacets": { + "type": "object", + "description": "Facets for filtering options.", + "properties": { + "plans": { + "type": "object", + "description": "Map of plan IDs to plan names.", + "additionalProperties": { + "type": "string" + }, + "nullable": true, + "x-isDateTime": false, + "x-description": [ + "Map of plan IDs to plan names." + ] + } + }, + "additionalProperties": false, + "x-description": [ + "Facets for filtering options." + ] + }, + "InvoicePDF": { + "description": "Invoice PDF document details.", + "properties": { + "url": { + "description": "A link to the PDF invoice.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "A link to the PDF invoice." + ] + }, + "status": { + "description": "The status of the PDF document. We generate invoice PDF asyncronously in batches. An invoice PDF document may not be immediately available to download. If status is 'ready', the PDF is ready to download. 'pending' means the PDF is not created but queued up. If you get this status, try again later.", + "type": "string", + "enum": [ + "ready", + "pending" + ], + "x-isDateTime": false, + "x-description": [ + "The status of the PDF document. We generate invoice PDF asyncronously in batches. An invoice PDF document may not", + "be immediately available to download. If status is 'ready', the PDF is ready to download. 'pending' means the PDF", + "is not created but queued up. If you get this status, try again later." + ] + } + }, + "type": "object", + "x-description": [ + "Invoice PDF document details." + ] + }, + "Order": { + "description": "The order object.", + "properties": { + "id": { + "description": "The ID of the order.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The ID of the order." + ] + }, + "status": { + "description": "The status of the subscription.", + "type": "string", + "enum": [ + "completed", + "past_due", + "pending", + "canceled", + "payment_failed_soft_decline", + "payment_failed_hard_decline" + ], + "x-isDateTime": false, + "x-description": [ + "The status of the subscription." + ] + }, + "owner": { + "description": "The UUID of the owner.", + "type": "string", + "format": "uuid", + "x-isDateTime": false, + "x-description": [ + "The UUID of the owner." + ] + }, + "address": { + "$ref": "#/components/schemas/Address" + }, + "company": { + "description": "The company name.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The company name." + ] + }, + "vat_number": { + "description": "An identifier used in many countries for value added tax purposes.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "An identifier used in many countries for value added tax purposes." + ] + }, + "billing_period_start": { + "description": "The time when the billing period of the order started.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The time when the billing period of the order started." + ] + }, + "billing_period_end": { + "description": "The time when the billing period of the order ended.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The time when the billing period of the order ended." + ] + }, + "billing_period_label": { + "description": "Descriptive information about the billing cycle.", + "properties": { + "formatted": { + "description": "The renderable label for the billing cycle.", + "type": "string", + "x-description": [ + "The renderable label for the billing cycle." + ] + }, + "month": { + "description": "The month of the billing cycle.", + "type": "string", + "x-description": [ + "The month of the billing cycle." + ] + }, + "year": { + "description": "The year of the billing cycle.", + "type": "string", + "x-description": [ + "The year of the billing cycle." + ] + }, + "next_month": { + "description": "The name of the next month following this billing cycle.", + "type": "string", + "x-description": [ + "The name of the next month following this billing cycle." + ] + } + }, + "type": "object", + "x-isDateTime": false, + "x-description": [ + "Descriptive information about the billing cycle." + ] + }, + "billing_period_duration": { + "description": "The duration of the billing period of the order in seconds.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The duration of the billing period of the order in seconds." + ] + }, + "paid_on": { + "description": "The time when the order was successfully charged.", + "type": "string", + "format": "date-time", + "nullable": true, + "x-isDateTime": true, + "x-description": [ + "The time when the order was successfully charged." + ] + }, + "total": { + "description": "The total of the order.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The total of the order." + ] + }, + "total_formatted": { + "description": "The total of the order, formatted with currency.", + "type": "integer", + "x-isDateTime": false, + "x-description": [ + "The total of the order, formatted with currency." + ] + }, + "components": { + "$ref": "#/components/schemas/Components" + }, + "currency": { + "description": "The order currency code.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The order currency code." + ] + }, + "invoice_url": { + "description": "A link to the PDF invoice.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "A link to the PDF invoice." + ] + }, + "last_refreshed": { + "description": "The time when the order was last refreshed.", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The time when the order was last refreshed." + ] + }, + "invoiced": { + "description": "The customer is invoiced.", + "type": "boolean", + "x-isDateTime": false, + "x-description": [ + "The customer is invoiced." + ] + }, + "line_items": { + "description": "The line items that comprise the order.", + "type": "array", + "items": { + "$ref": "#/components/schemas/LineItem" + }, + "x-isDateTime": false, + "x-description": [ + "The line items that comprise the order." + ] + }, + "_links": { + "description": "Links to related API endpoints.", + "properties": { + "invoices": { + "description": "Link to related Invoices API. Use this to retrieve invoices related to this order.", + "properties": { + "href": { + "description": "URL of the link", + "type": "string", + "x-description": [ + "URL of the link" + ] + } + }, + "type": "object", + "x-description": [ + "Link to related Invoices API. Use this to retrieve invoices related to this order." + ] + } + }, + "type": "object", + "x-description": [ + "Links to related API endpoints." + ] + } + }, + "type": "object", + "x-description": [ + "The order object." + ] + }, + "PlanRecords": { + "description": "The plan record object.", + "properties": { + "id": { + "description": "The unique ID of the plan record.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The unique ID of the plan record." + ] + }, + "owner": { + "description": "The UUID of the owner.", + "type": "string", + "format": "uuid", + "x-isDateTime": false, + "x-description": [ + "The UUID of the owner." + ] + }, + "subscription_id": { + "description": "The ID of the subscription this record pertains to.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The ID of the subscription this record pertains to." + ] + }, + "sku": { + "description": "The product SKU of the plan that this record represents.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The product SKU of the plan that this record represents." + ] + }, + "plan": { + "description": "The machine name of the plan that this record represents.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The machine name of the plan that this record represents." + ] + }, + "options": { + "type": "array", + "items": { + "description": "The SKU of an option.", + "type": "string" + }, + "x-isDateTime": false + }, + "start": { + "description": "The start timestamp of this plan record (ISO 8601).", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The start timestamp of this plan record (ISO 8601)." + ] + }, + "end": { + "description": "The end timestamp of this plan record (ISO 8601).", + "type": "string", + "format": "date-time", + "nullable": true, + "x-isDateTime": true, + "x-description": [ + "The end timestamp of this plan record (ISO 8601)." + ] + }, + "status": { + "description": "The status of the subscription during this record: active or suspended.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The status of the subscription during this record: active or suspended." + ] + } + }, + "type": "object", + "x-description": [ + "The plan record object." + ] + }, + "Usage": { + "description": "The usage object.", + "properties": { + "id": { + "description": "The unique ID of the usage record.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The unique ID of the usage record." + ] + }, + "subscription_id": { + "description": "The ID of the subscription.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The ID of the subscription." + ] + }, + "usage_group": { + "description": "The type of usage that this record represents.", + "type": "string", + "x-isDateTime": false, + "x-description": [ + "The type of usage that this record represents." + ] + }, + "quantity": { + "description": "The quantity used.", + "type": "number", + "x-isDateTime": false, + "x-description": [ + "The quantity used." + ] + }, + "start": { + "description": "The start timestamp of this usage record (ISO 8601).", + "type": "string", + "format": "date-time", + "x-isDateTime": true, + "x-description": [ + "The start timestamp of this usage record (ISO 8601)." + ] + } + }, + "type": "object", + "x-description": [ + "The usage object." + ] + }, + "ResourceConfig": { + "type": "object", + "properties": { + "profile_size": { + "type": "string", + "nullable": true, + "description": "Profile size (e.g. \"0.5\", \"1\", \"2\")", + "example": "2", + "x-description": [ + "Profile size (e.g. \"0.5\", \"1\", \"2\")" + ] + } + } + } + }, + "parameters": { + "filter_invoice_type": { + "name": "filter[type]", + "in": "query", + "description": "The invoice type. Use invoice for standard invoices, credit_memo for refund/credit invoices.", + "schema": { + "type": "string", + "enum": [ + "credit_memo", + "invoice" + ] + }, + "x-description": [ + "The invoice type. Use invoice for standard invoices, credit_memo for", + "refund/credit invoices." + ] + }, + "filter_order_id": { + "name": "filter[order_id]", + "in": "query", + "description": "The order id of Invoice.", + "schema": { + "type": "string" + }, + "x-description": [ + "The order id of Invoice." + ] + }, + "filter_invoice_status": { + "name": "filter[status]", + "in": "query", + "description": "The status of the invoice.", + "schema": { + "type": "string", + "enum": [ + "paid", + "charged_off", + "pending", + "refunded", + "canceled", + "refund_pending" + ] + }, + "x-description": [ + "The status of the invoice." + ] + }, + "mode": { + "name": "mode", + "in": "query", + "description": "The output mode.", + "schema": { + "type": "string", + "enum": [ + "details" + ] + }, + "x-description": [ + "The output mode." + ] + }, + "filter_order_status": { + "name": "filter[status]", + "in": "query", + "description": "The status of the order.", + "schema": { + "type": "string", + "enum": [ + "completed", + "past_due", + "pending", + "canceled", + "payment_failed_soft_decline", + "payment_failed_hard_decline" + ] + }, + "x-description": [ + "The status of the order." + ] + }, + "filter_order_total": { + "name": "filter[total]", + "in": "query", + "description": "The total of the order.", + "schema": { + "type": "integer" + }, + "x-description": [ + "The total of the order." + ] + }, + "record_end": { + "name": "filter[end]", + "in": "query", + "description": "The end of the observation period for the record. E.g. filter[end]=2018-01-01 will display all records that were active on (i.e. they started before) 2018-01-01", + "schema": { + "type": "string", + "format": "date-time" + }, + "x-description": [ + "The end of the observation period for the record. E.g. filter[end]=2018-01-01", + "will display all records that were active on (i.e. they started before)", + "2018-01-01" + ] + }, + "record_ended_at": { + "name": "filter[ended_at]", + "in": "query", + "description": "The record's end timestamp. You can use this filter to list records ended after, or before a certain time. E.g. filter[ended_at][value]=2020-01-01&filter[ended_at][operator]=>", + "schema": { + "type": "string", + "format": "date-time" + }, + "x-description": [ + "The record's end timestamp. You can use this filter to list records ended after,", + "or before a certain time. E.g.", + "filter[ended_at][value]=2020-01-01&filter[ended_at][operator]=>" + ] + }, + "record_status": { + "name": "filter[status]", + "in": "query", + "description": "The status of the plan record. ", + "schema": { + "type": "string", + "enum": [ + "active", + "suspended" + ] + }, + "x-description": [ + "The status of the plan record." + ] + }, + "record_usage_group": { + "name": "filter[usage_group]", + "in": "query", + "description": "Filter records by the type of usage.", + "schema": { + "type": "string", + "enum": [ + "storage", + "environments", + "user_licenses" + ] + }, + "x-description": [ + "Filter records by the type of usage." + ] + }, + "record_start": { + "name": "filter[start]", + "in": "query", + "description": "The start of the observation period for the record. E.g. filter[start]=2018-01-01 will display all records that were active (i.e. did not end) on 2018-01-01", + "schema": { + "type": "string", + "format": "date-time" + }, + "x-description": [ + "The start of the observation period for the record. E.g.", + "filter[start]=2018-01-01 will display all records that were active (i.e. did not", + "end) on 2018-01-01" + ] + }, + "record_started_at": { + "name": "filter[started_at]", + "in": "query", + "description": "The record's start timestamp. You can use this filter to list records started after, or before a certain time. E.g. filter[started_at][value]=2020-01-01&filter[started_at][operator]=>", + "schema": { + "type": "string", + "format": "date-time" + }, + "x-description": [ + "The record's start timestamp. You can use this filter to list records started", + "after, or before a certain time. E.g.", + "filter[started_at][value]=2020-01-01&filter[started_at][operator]=>" + ] + }, + "discountId": { + "name": "id", + "in": "path", + "description": "The ID of the organization discount", + "required": true, + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the organization discount" + ] + }, + "subscription_id": { + "name": "subscriptionId", + "in": "path", + "description": "The ID of the subscription", + "required": true, + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the subscription" + ] + }, + "filter_subscription_id": { + "name": "filter[subscription_id]", + "in": "query", + "description": "The ID of the subscription", + "required": false, + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the subscription" + ] + }, + "subscription_plan": { + "name": "plan", + "in": "query", + "description": "The plan type of the subscription.", + "schema": { + "type": "string", + "enum": [ + "development", + "standard", + "medium", + "large", + "xlarge", + "2xlarge" + ] + }, + "x-description": [ + "The plan type of the subscription." + ] + }, + "filter_subscription_plan": { + "name": "filter[plan]", + "in": "query", + "description": "The plan type of the subscription.", + "schema": { + "type": "string", + "enum": [ + "development", + "standard", + "medium", + "large", + "xlarge", + "2xlarge" + ] + }, + "x-description": [ + "The plan type of the subscription." + ] + }, + "subscription_environments": { + "name": "environments", + "in": "query", + "description": "The number of environments which can be provisioned on the project.", + "schema": { + "type": "integer", + "default": null + }, + "x-description": [ + "The number of environments which can be provisioned on the project." + ] + }, + "subscription_storage": { + "name": "storage", + "in": "query", + "description": "The total storage available to each environment, in MiB. Only multiples of 1024 are accepted as legal values.", + "schema": { + "type": "integer", + "default": null + }, + "x-description": [ + "The total storage available to each environment, in MiB. Only multiples of 1024", + "are accepted as legal values." + ] + }, + "subscription_user_licenses": { + "name": "user_licenses", + "in": "query", + "description": "The number of user licenses.", + "schema": { + "type": "integer" + }, + "x-description": [ + "The number of user licenses." + ] + }, + "page": { + "name": "page", + "in": "query", + "description": "Page to be displayed. Defaults to 1.", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-description": [ + "Page to be displayed. Defaults to 1." + ] + }, + "user_id": { + "name": "userId", + "in": "path", + "description": "The UUID of the user", + "required": true, + "schema": { + "type": "string" + }, + "x-description": [ + "The UUID of the user" + ] + }, + "filter_ticket_id": { + "name": "filter[ticket_id]", + "in": "query", + "description": "The ID of the ticket.", + "schema": { + "type": "integer" + }, + "x-description": [ + "The ID of the ticket." + ] + }, + "filter_created": { + "name": "filter[created]", + "in": "query", + "description": "ISO dateformat expected. The time when the support ticket was created.", + "schema": { + "type": "string", + "format": "date-time" + }, + "x-description": [ + "ISO dateformat expected. The time when the support ticket was created." + ] + }, + "filter_updated": { + "name": "filter[updated]", + "in": "query", + "description": "ISO dateformat expected. The time when the support ticket was updated.", + "schema": { + "type": "string", + "format": "date-time" + }, + "x-description": [ + "ISO dateformat expected. The time when the support ticket was updated." + ] + }, + "filter_type": { + "name": "filter[type]", + "in": "query", + "description": "The type of the support ticket.", + "schema": { + "type": "string", + "enum": [ + "problem", + "task", + "incident", + "question" + ] + }, + "x-description": [ + "The type of the support ticket." + ] + }, + "filter_priority": { + "name": "filter[priority]", + "in": "query", + "description": "The priority of the support ticket.", + "schema": { + "type": "string", + "enum": [ + "low", + "normal", + "high", + "urgent" + ] + }, + "x-description": [ + "The priority of the support ticket." + ] + }, + "filter_ticket_status": { + "name": "filter[status]", + "in": "query", + "description": "The status of the support ticket.", + "schema": { + "type": "string", + "enum": [ + "closed", + "deleted", + "hold", + "new", + "open", + "pending", + "solved" + ] + }, + "x-description": [ + "The status of the support ticket." + ] + }, + "filter_requester_id": { + "name": "filter[requester_id]", + "in": "query", + "description": "UUID of the ticket requester. Converted from the ZID value.", + "schema": { + "type": "string", + "format": "uuid" + }, + "x-description": [ + "UUID of the ticket requester. Converted from the ZID value." + ] + }, + "filter_submitter_id": { + "name": "filter[submitter_id]", + "in": "query", + "description": "UUID of the ticket submitter. Converted from the ZID value.", + "schema": { + "type": "string", + "format": "uuid" + }, + "x-description": [ + "UUID of the ticket submitter. Converted from the ZID value." + ] + }, + "filter_assignee_id": { + "name": "filter[assignee_id]", + "in": "query", + "description": "UUID of the ticket assignee. Converted from the ZID value.", + "schema": { + "type": "string", + "format": "uuid" + }, + "x-description": [ + "UUID of the ticket assignee. Converted from the ZID value." + ] + }, + "filter_has_incidents": { + "name": "filter[has_incidents]", + "in": "query", + "description": "Whether or not this ticket has incidents.", + "schema": { + "type": "boolean" + }, + "x-description": [ + "Whether or not this ticket has incidents." + ] + }, + "filter_due": { + "name": "filter[due]", + "in": "query", + "description": "ISO dateformat expected. A time that the ticket is due at.", + "schema": { + "type": "string", + "format": "date-time" + }, + "x-description": [ + "ISO dateformat expected. A time that the ticket is due at." + ] + }, + "InvitationID": { + "name": "invitation_id", + "in": "path", + "required": true, + "description": "The ID of the invitation.", + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the invitation." + ] + }, + "OrganizationID": { + "name": "organization_id", + "in": "path", + "required": true, + "description": "The ID of the organization.", + "schema": { + "type": "string", + "format": "ulid" + }, + "x-description": [ + "The ID of the organization." + ] + }, + "ProjectID": { + "name": "project_id", + "in": "path", + "required": true, + "description": "The ID of the project.", + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the project." + ] + }, + "TeamID": { + "name": "team_id", + "in": "path", + "required": true, + "description": "The ID of the team.", + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the team." + ] + }, + "UserID": { + "name": "user_id", + "in": "path", + "required": true, + "description": "The ID of the user.", + "schema": { + "type": "string", + "example": "d81c8ee2-44b3-429f-b944-a33ad7437690", + "format": "uuid" + }, + "x-description": [ + "The ID of the user." + ] + }, + "OrganizationIDName": { + "in": "path", + "name": "organization_id", + "description": "The ID of the organization.
\nPrefix with name= to retrieve the organization by name instead.\n", + "required": true, + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the organization. Prefix with name= to retrieve the organization by", + "name instead." + ] + }, + "OrderID": { + "in": "path", + "name": "order_id", + "description": "The ID of the order.", + "required": true, + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the order." + ] + }, + "SubscriptionID": { + "in": "path", + "name": "subscription_id", + "description": "The ID of the subscription.", + "required": true, + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the subscription." + ] + }, + "InvoiceID": { + "in": "path", + "name": "invoice_id", + "description": "The ID of the invoice.", + "required": true, + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the invoice." + ] + }, + "RegionID": { + "in": "path", + "name": "region_id", + "description": "The ID of the region.", + "required": true, + "schema": { + "type": "string" + }, + "x-description": [ + "The ID of the region." + ] + }, + "PageSize": { + "in": "query", + "name": "page[size]", + "description": "Determines the number of items to show.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": null + }, + "x-description": [ + "Determines the number of items to show." + ] + }, + "PageBefore": { + "in": "query", + "name": "page[before]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + }, + "x-description": [ + "Pagination cursor. This is automatically generated as necessary and provided in", + "HAL links (_links); it should not be constructed externally." + ] + }, + "PageAfter": { + "in": "query", + "name": "page[after]", + "description": "Pagination cursor. This is automatically generated as necessary and provided in HAL links (_links); it should not be constructed externally.", + "schema": { + "type": "string" + }, + "x-description": [ + "Pagination cursor. This is automatically generated as necessary and provided in", + "HAL links (_links); it should not be constructed externally." + ] + }, + "PageSizeAccess": { + "in": "query", + "name": "page[size]", + "description": "Determines the number of items to show.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 200, + "default": null + }, + "x-description": [ + "Determines the number of items to show." + ] + }, + "TimeRangeFrom": { + "in": "query", + "name": "from", + "description": "The start of the time frame for the query. Inclusive.", + "schema": { + "$ref": "#/components/schemas/DateTimeFilter" + }, + "x-description": [ + "The start of the time frame for the query. Inclusive." + ] + }, + "TimeRangeTo": { + "in": "query", + "name": "to", + "description": "The end of the time frame for the query. Exclusive.", + "schema": { + "$ref": "#/components/schemas/DateTimeFilter" + }, + "x-description": [ + "The end of the time frame for the query. Exclusive." + ] + }, + "TimeRangeInterval": { + "in": "query", + "name": "interval", + "description": "The interval by which the query groups the results. of the time frame for the query. Exclusive.", + "schema": { + "type": "string", + "enum": [ + "day", + "month", + "year" + ] + }, + "x-description": [ + "The interval by which the query groups the results. of the time frame for the", + "query. Exclusive." + ] + }, + "FilterUpdatedAt": { + "in": "query", + "name": "filter[updated_at]", + "description": "Allows filtering by `updated_at` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/DateTimeFilter" + }, + "x-description": [ + "Allows filtering by `updated_at` using one or more operators." + ] + }, + "FilterCreatedAt": { + "in": "query", + "name": "filter[created_at]", + "description": "Allows filtering by `created_at` using one or more operators.", + "style": "deepObject", + "explode": true, + "schema": { + "$ref": "#/components/schemas/DateTimeFilter" + }, + "x-description": [ + "Allows filtering by `created_at` using one or more operators." + ] + } + }, + "securitySchemes": { + "BearerAuth": { + "type": "http", + "scheme": "bearer" + }, + "OAuth2": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "tokenUrl": "https://auth.api.platform.sh/oauth2/token", + "refreshUrl": "https://auth.api.platform.sh/oauth2/token", + "scopes": {}, + "authorizationUrl": "https://auth.api.platform.sh/oauth2/authorize" + } + }, + "description": "" + }, + "OAuth2Admin": { + "type": "oauth2", + "flows": { + "clientCredentials": { + "tokenUrl": "https://auth.api.platform.sh/oauth2/token", + "refreshUrl": "", + "scopes": { + "admin": "administrative operations" + } + } + }, + "description": "" + } + }, + "responses": { + "BadRequest": { + "description": "Bad Request", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "Forbidden": { + "description": "Forbidden", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "NotFound": { + "description": "Not Found", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "Conflict": { + "description": "Conflict", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "ServiceUnavailable": { + "description": "Service Unavailable", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "NoContent": { + "description": "No Content" + } + } + }, + "x-tagGroups": [ + { + "name": "Organization Administration", + "tags": [ + "Organizations", + "Organization Members", + "Organization Invitations", + "Organization Projects", + "Add-ons" + ] + }, + { + "name": "Project Administration", + "tags": [ + "Project", + "Domain Management", + "Cert Management", + "Certificate Provisioner", + "Project Variables", + "Repository", + "Third-Party Integrations", + "Support" + ] + }, + { + "name": "Environments", + "tags": [ + "Environment", + "Environment Backups", + "Environment Type", + "Environment Variables", + "Routing", + "Source Operations", + "Runtime Operations", + "Deployment", + "Autoscaling" + ] + }, + { + "name": "User Activity", + "tags": [ + "Project Activity", + "Environment Activity" + ] + }, + { + "name": "Project Access", + "tags": [ + "Project Invitations", + "Teams", + "Team Access", + "User Access" + ] + }, + { + "name": "Account Management", + "tags": [ + "API Tokens", + "Connections", + "MFA", + "Users", + "User Profiles", + "SSH Keys", + "Plans" + ] + }, + { + "name": "Billing", + "tags": [ + "Organization Management", + "Subscriptions", + "Orders", + "Invoices", + "Discounts", + "Vouchers", + "Records", + "Profiles" + ] + }, + { + "name": "Global Info", + "tags": [ + "Project Discovery", + "References", + "Regions" + ] + }, + { + "name": "Internal APIs", + "tags": [ + "Project Settings", + "Environment Settings", + "Deployment Target", + "System Information", + "Container Profile" + ] + } + ] +} \ No newline at end of file diff --git a/scripts/gen_node.sh b/scripts/gen_node.sh index a0c05c2..b0361f3 100755 --- a/scripts/gen_node.sh +++ b/scripts/gen_node.sh @@ -1,4 +1,4 @@ -#!/usr/bin/bash +#!/usr/bin/env bash echo "Clean old build..." rm -rf ./src/apis-gen diff --git a/scripts/help.sh b/scripts/help.sh new file mode 100644 index 0000000..04d821f --- /dev/null +++ b/scripts/help.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +echo "" +echo " build - Compile TypeScript files to JavaScript" +echo " build:watch - Watch mode compilation" +echo " clean - Remove dist directory" +echo " fix:all - Run all linters and formatters in fix mode" +echo " fix:es - Fix ESLint issues" +echo " fix:prettier - Format code with Prettier" +echo " lint:all - Run all linters" +echo " lint:es - Check ESLint errors" +echo " lint:prettier - Check code formatting" +echo " qa - Run linting and tests" +echo " qa:all - Full build, lint and test pipeline" +echo " run - Execute the compiled app" +echo " spec:clean - Clean generated API and model files" +echo " spec:dl - Download OpenAPI spec" +echo " spec:generate - Generate API from OpenAPI spec" +echo " spec:patch - Apply patches to OpenAPI spec" +echo " test - Run unit tests" +echo " test:all - Run all unit tests" +echo " test:coverage - Generate test coverage report" +echo " test:coverage:ci - CI coverage report" +echo " test:integration - Run integration tests" +echo " test:watch - Watch mode for tests" +echo "" diff --git a/src/.openapi-generator-ignore b/src/.openapi-generator-ignore new file mode 100644 index 0000000..7aed4cb --- /dev/null +++ b/src/.openapi-generator-ignore @@ -0,0 +1,5 @@ +# OpenAPI Generator Ignore + +apis/index.ts +models/index.ts +index.ts diff --git a/src/app.ts b/src/app.ts index 95a10f0..149ef9b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,96 +1,182 @@ -import { SubscriptionStatusEnum } from "./apis-gen/models/index.js"; -import { UpsunClient, UpsunConfig } from "./index.js"; -import dotenv from "dotenv"; +/* eslint-disable no-console */ +import { exit } from 'process'; +import { + DedicatedDeploymentTargetCreateInputTypeEnum, + SubscriptionStatusEnum, +} from './model/index.js'; +import { UpsunClient, UpsunConfig } from './upsun.js'; +import dotenv from 'dotenv'; +import { ResponseError } from './index.js'; +import { DeploymentResourceGroup } from './core/model.js'; dotenv.config(); -const DISABLED: boolean = true; -const FULL_TEST: boolean = false; +const DISABLED: boolean = false; +const FULL_TEST: boolean = true; const MODE_USE: string = 'API'; // 'API' or 'BEARER' +const projectTestId = 'iok5pcum4s4au'; // Replace with your project ID -function delay(ms: number) { - return new Promise( resolve => setTimeout(resolve, ms) ); +function delay(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); } // Main class of Upsun-dsk-node. let upsun: UpsunClient; if (MODE_USE === 'API') { - - upsun = new UpsunClient({ apiKey: process.env.UPSUN_CLI_TOKEN || "UPSUN_CLI_TOKEN is not define !" } as UpsunConfig); + upsun = new UpsunClient({ + apiKey: process.env.UPSUN_CLI_TOKEN || 'UPSUN_CLI_TOKEN is not define !', + } as UpsunConfig); // (If needed) Check authentication - if (DISABLED || await upsun.authenticate()) { - console.log("Authentication successful"); + if (DISABLED || (await upsun.authenticate())) { + console.log('Authentication successful'); } - } else if (MODE_USE === 'BEARER') { - upsun = new UpsunClient(); - upsun.setBearerToken("token"); - + upsun.setBearerToken('Your_Bearer_Token_Here'); // Replace with your bearer token } else { - throw new Error("Invalid MODE_USE value. Use 'API' or 'BEARER'."); + throw new Error('Invalid MODE_USE value. Use API or BEARER.'); } -const orgs = await upsun.organization.list(); -console.log(orgs); +console.log("--- it's me ---"); +const me = await upsun.users.me(); +console.log(me); -const orgName = "Perso-home"; // Replace with your organization ID -const org = orgs.items?.find((p) => p.label === orgName) ?? null; -console.log(org); +console.log('--- List Organizations ---'); +const orgs = await upsun.organizations.list(); +console.log(orgs); if (FULL_TEST) { try { - if (org && org.id) { + const orgs = await upsun.organizations.list({ + filterName: { eq: 'florent-huck' }, // Replace with your organization name (ex: 'perso-home') + filterCapabilities: { eq: 'project-create' }, // Filter organizations where the user has the 'project-create' capability + }); + + const orgName = 'florent-huck'; // Replace with your organization name (ex: 'perso-home') + const org = orgs.items?.find(p => p.name === orgName) ?? null; + if (org && org?.id) { // Create Project - const subCreated = await upsun.project.create(org.id, "eu-3.platform.sh", "Demo", "main"); - - let prjCreated = await upsun.project.getSubscription(org.id, subCreated.id || ""); - while (prjCreated.status !== SubscriptionStatusEnum.Active) { - console.log("Waiting for project to be active..."); + // console.log('--- Create Project ---'); + // const subCreated = await upsun.projects.create( + // org?.id, + // 'eu-5.platform.sh', + // 'Demo test from sdk-node '+new Date().toISOString(), + // 'upsun/flexible', + // 'main' + // ); + + // const maxAttempts = 12; + // let prjCreated = null; + /* for (let attempt = 1; attempt <= maxAttempts; attempt++) { + try { + prjCreated = await upsun.projects.getSubscription(org!.id, subCreated.id || ''); + console.log(`Statut de la souscription : ${prjCreated.status}`); + if (prjCreated.status === SubscriptionStatusEnum.ACTIVE) { + break; + } + } catch (error) { + if (error instanceof ResponseError && [404, 202].includes(error.response.status)) { + console.log(`Ressource non prête (code ${error.response.status}), attente…`); + } else { + throw error; + } + } await delay(10000); - prjCreated = await upsun.project.getSubscription(org.id, subCreated.id || ""); } - // Sample code to get all projects - // const orgId = "name=Perso-home"; // Replace with your organization ID - const prjs = await upsun.project.list(org.id); + if (!prjCreated || prjCreated.status !== SubscriptionStatusEnum.ACTIVE) { + throw new Error('Subscription never transitioned to ACTIVE state within the allotted time'); + } else { + console.log('Project created:', prjCreated); + } */ - // Select a specific project - const prjName = "POC-mcp-stack"; // Replace with your project name - const prj = prjs.items?.find((p) => p.projectTitle === prjName) ?? null; - console.log(prj); + // Sample code to get a project + // console.log('--- Get project ---'); + // prjCreatedObject = await upsun.projects.get(prjCreated.projectId || ''); + // console.log(prjCreatedObject); // Wait 15 minutes before redeploying (test renew access token) - DISABLED || await delay(6000*15); + + //DISABLED || (await delay(6000 * 15)); // Work with project - if (prj && prj.projectId) { - - const envName = "main"; // Replace with your environment name - - const res = await upsun.resource.get(prj.projectId, envName); + const prj = await upsun.projects.get(projectTestId || ''); + + if (prj && prj.id) { + const envName = 'main'; // Replace with your environment name + + console.log('--- Get Resources ---'); + const res = await upsun.resources.get( + prj.id, + prj.defaultBranch || 'main', + DeploymentResourceGroup.webapps, + 'app--app-worker', + ); console.log(res); + console.log('--- Set Resources ---'); + const response = await upsun.resources.set( + prj.id || '', + prj.defaultBranch || 'main', + { + app: { + resources: { profileSize: '1' }, + disk: 1024, + instanceCount: 2, + }, + }, + { + mysql: { + resources: { profileSize: '1' }, + disk: 2048, + }, + }, + { + 'app--app-worker': { + resources: { profileSize: '1' }, + instanceCount: 2, + }, + }, + ); + // Get console URL - // const web = await upsun.route.web(prj.projectId); - // console.log(web.ui); + const route = await upsun.routes.list(prj.id, prj.defaultBranch || 'main'); + console.log(route); // Redeploy the project - const result = await upsun.environment.redeploy(prj.projectId, envName); + const result = await upsun.environments.redeploy(prj.id, envName); console.log(result); // List all activities - const activities = await upsun.activity.list(prj.projectId); + const activities = await upsun.activities.list(prj.id); console.log(activities); + const latestActivity = activities[0]; + if (latestActivity && latestActivity.id) { + // Get activity details + const activityDetails = await upsun.activities.get(prj.id, latestActivity.id); + console.log(activityDetails); + } + // List routes of prj/env - const routes = await upsun.route.list(prj.projectId, envName); + const routes = await upsun.routes.list(prj.id, envName); console.log(routes); } } + await upsun.environments.activate(projectTestId, 'main'); } catch (error) { - console.error("An error occurred:", error); + console.error(error); + } finally { + if (FULL_TEST) { + console.log('--- Cleanup: Delete Project ---'); + try { + // await upsun.projects.delete(prjCreatedObject?.id || ''); + console.log('Project deleted successfully'); + } catch (deleteError) { + console.error('Error deleting project:', deleteError); + } + } } } diff --git a/src/core/index.ts b/src/core/index.ts index 5aec3ff..61193ac 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -1,125 +1,3 @@ -type TokenResponse = { - access_token: string; - refresh_token: string; - expires_in: number; // en secondes - token_type: string; -}; - -/** - * OAuth2Client class for handling OAuth2 authentication. - * This class provides methods for exchanging an API token for an access token, - * refreshing the access token, and ensuring that the access token is valid. - * It also provides a method to get the authorization header for API requests. - */ -export class OAuth2Client { - private typeToken: string | null = null; - private accessToken: string | null = null; - private refreshToken: string | null = null; - private tokenExpiry: number = 0; // timestamp en ms - - /** - * Constructor for the OAuth2Client class. - * - * @param tokenEndpoint - The endpoint for exchanging the API token for an access token. - * @param clientId - The client ID for OAuth2 authentication. - * @param clientSecret - The client secret for OAuth2 authentication. - */ - constructor( - private readonly tokenEndpoint: string, - private readonly clientId: string, - private readonly clientSecret: string, - ) {} - - /** - * Exchanges the API token for an access token. - * - * @returns {Promise} - Returns true if the exchange was successful, false otherwise. - */ - async exchangeCodeForToken(): Promise { - const params = new URLSearchParams({ - grant_type: 'api_token', - api_token: this.clientSecret, - }); - - const response = await fetch(this.tokenEndpoint, { - method: 'POST', - headers: { - 'Authorization': 'Basic ' + btoa('platform-api-user:'), - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: params.toString(), - }); - - if (!response.ok) { - throw new Error('Token exchange failed'); - return false; - } - - const data: TokenResponse = await response.json(); - this.storeTokenData(data); - - return true; - } - - /** - * Stores the token data in the class properties. - * - * @param data - The token response data. - */ - private storeTokenData(data: TokenResponse) { - this.typeToken = data.token_type; - this.accessToken = data.access_token; - this.refreshToken = data.refresh_token; - this.tokenExpiry = Date.now() + data.expires_in * 1000; - } - - private async refreshAccessToken(): Promise { - if (!this.refreshToken) - throw new Error('No refresh token available'); - - const params = new URLSearchParams({ - grant_type: 'refresh_token', - refresh_token: this.refreshToken, - client_id: this.clientId, - }); - - const response = await fetch(this.tokenEndpoint, { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: params.toString(), - }); - - if (!response.ok) - throw new Error('Token refresh failed'); - - const data: TokenResponse = await response.json(); - this.storeTokenData(data); - } - - /** - * Ensures that the access token is valid and refreshes it if necessary. - * - * @returns {Promise} - Returns a promise that resolves when the token is valid. - */ - private async ensureValidToken(): Promise { - const buffer = 60 * 1000; - if (!this.accessToken || Date.now() > this.tokenExpiry - buffer) { - //await this.refreshAccessToken(); - await this.exchangeCodeForToken(); - } - } - - /** - * Gets the authorization header for API requests. - * - * @returns {Promise} - Returns a promise that resolves to the authorization header. - */ - async getAuthorization(): Promise { - await this.ensureValidToken(); - - //TODO use typeToken. - return `Bearer ${this.accessToken}`; - } -} +export * from './tasks/index.js'; +export * from './oauth-provider.js'; +export * from './runtime.js'; diff --git a/src/core/model.ts b/src/core/model.ts new file mode 100644 index 0000000..e0625e3 --- /dev/null +++ b/src/core/model.ts @@ -0,0 +1,73 @@ +import { + ListOrgInvitesRequest, + ListOrgMembersRequest, + ListOrgOrdersRequest, + ListOrgPlanRecordsRequest, + ListOrgProjectsRequest, + ListOrgsRequest, + ListOrgUsageRecordsRequest, + ListProjectInvitesRequest, + ListProjectTeamAccessRequest, + ListProjectUserAccessRequest, + ListTeamMembersRequest, + ListTeamProjectAccessRequest, + ListUserExtendedAccessRequest, + ListUserOrgsRequest, + ListUserProjectAccessRequest, + ListUserTeamsRequest, +} from '../api/index.js'; +import { + CertificateCreateInput, + CreateOrgSubscriptionRequest, + CreateProjectInviteRequest, + EnvironmentVariableCreateInput, + IntegrationCreateInput, + ProjectVariableCreateInput, +} from '../model/index.js'; + +// Type creation for request parameters that omit required fields from the original input types +export type CertificateCreateParams = Omit; +export type FilterListOrgInvites = Omit; +export type CreateProjectInvite = Omit; +export type ListProjectInvites = Omit; + +// used in OrganizationsTask and ProjectsTask +export type FilterListUser = Omit; +export type FilterListMembers = Omit; +export type FilterListOrders = Omit; +export type FilterListPlanRecords = Omit; +export type FilterListUsageRecords = Omit; +export type FilterListOrgs = Omit; + +// used in ProjectTasks +export type IntegrationCreateData = Omit; +export type ProjectCreateRequest = Omit; +export type FilterListOrgProjects = Omit; + +// used in TeamsTask +export type FilterListTeamProjectAccess = Omit; +export type FilterListProjectTeamAccess = Omit; +export type FilterListUserTeams = Omit; +export type FilterListTeamMembers = Omit; + +// used in VariablesTask +export type ProjectVariableCreateParams = Omit; +export type EnvironmentVariableCreateParams = Omit< + EnvironmentVariableCreateInput, + 'name' | 'value' +>; + +// used in ResourcesTask +export const DeploymentResourceGroup = { + webapps: 'webapps', + services: 'services', + workers: 'workers', +} as const; + +export type DeploymentResourceGroup = + (typeof DeploymentResourceGroup)[keyof typeof DeploymentResourceGroup]; + +// used in UsersTasks +export type FilterListProjectUserAccess = Omit; +export type FilterListUserProjectAccess = Omit; +export type FilterListUserExtendedAccess = Omit; diff --git a/src/core/oauth-provider.ts b/src/core/oauth-provider.ts new file mode 100644 index 0000000..4f8c6c5 --- /dev/null +++ b/src/core/oauth-provider.ts @@ -0,0 +1,130 @@ +type TokenResponse = { + access_token: string; + refresh_token: string; + expires_in: number; // en secondes + token_type: string; +}; + +/** + * OAuth2Client class for handling OAuth2 authentication. + * This class provides methods for exchanging an API token for an access token, + * refreshing the access token, and ensuring that the access token is valid. + * It also provides a method to get the authorization header for API requests. + */ +export class OAuth2Client { + private typeToken: string | null = null; + private accessToken: string | null = null; + private refreshToken: string | null = null; + private tokenExpiry: number = 0; // timestamp en ms + + /** + * Constructor for the OAuth2Client class. + * + * @param tokenEndpoint - The endpoint for exchanging the API token for an access token. + * @param clientId - The client ID for OAuth2 authentication. + * @param clientSecret - The client secret for OAuth2 authentication. + */ + constructor( + private readonly tokenEndpoint: string, + private readonly clientId: string, + private readonly clientSecret: string, + ) {} + + /** + * Exchanges the API token for an access token. + * + * @returns {Promise} - Returns true if the exchange was successful, false otherwise. + */ + async exchangeCodeForToken(): Promise { + const params = new URLSearchParams({ + grant_type: 'api_token', + api_token: this.clientSecret, + }); + + const response = await fetch(this.tokenEndpoint, { + method: 'POST', + headers: { + Authorization: 'Basic ' + btoa('platform-api-user:'), + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: params.toString(), + }); + + if (!response.ok) { + throw new Error('Token exchange failed'); + } + + const data: TokenResponse = await response.json(); + this.storeTokenData(data); + + return true; + } + + /** + * Stores the token data in the class properties. + * + * @param data - The token response data. + */ + private storeTokenData(data: TokenResponse): void { + this.typeToken = data.token_type; + this.accessToken = data.access_token; + this.refreshToken = data.refresh_token; + this.tokenExpiry = Date.now() + data.expires_in * 1000; + } + + private async refreshAccessToken(): Promise { + if (!this.refreshToken) throw new Error('No refresh token available'); + + const params = new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: this.refreshToken, + client_id: this.clientId, + }); + + const response = await fetch(this.tokenEndpoint, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: params.toString(), + }); + + if (!response.ok) throw new Error('Token refresh failed'); + + const data: TokenResponse = await response.json(); + this.storeTokenData(data); + } + + /** + * Ensures that the access token is valid and refreshes it if necessary. + * + * @returns {Promise} - Returns a promise that resolves when the token is valid. + */ + private async ensureValidToken(): Promise { + const buffer = 60 * 1000; + if (!this.accessToken || Date.now() > this.tokenExpiry - buffer) { + if (this.refreshToken) { + try { + await this.refreshAccessToken(); + return; + } catch { + // fall back to exchanging a new token when refresh fails + this.accessToken = null; + } + } + await this.exchangeCodeForToken(); + } + } + + /** + * Gets the authorization header for API requests. + * + * @returns {Promise} - Returns a promise that resolves to the authorization header. + */ + async getAuthorization(): Promise { + await this.ensureValidToken(); + + //TODO use typeToken. + return `${this.accessToken}`; + } +} diff --git a/src/core/tasks/activities.ts b/src/core/tasks/activities.ts new file mode 100644 index 0000000..a1ca324 --- /dev/null +++ b/src/core/tasks/activities.ts @@ -0,0 +1,99 @@ +import { EnvironmentActivityApi, ProjectActivityApi } from '../../api/index.js'; +import { AcceptedResponse, Activity } from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; + +export class ActivitiesTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private prjActApi: ProjectActivityApi, + private envActApi: EnvironmentActivityApi, + ) { + super(client); + } + + /** + * Cancel an activity for a project or environment. The API will return a 202 Accepted response if the cancellation + * request has been accepted, but the client should check the activity's details to confirm whether the cancellation + * was successful or not. + * @param projectId - The ID of the project. + * @param activityId - The ID of the activity to cancel. + * @param environmentId - (Optional) The ID of the environment. If not provided, the activity is assumed to be a project-level activity. + * @returns An AcceptedResponse indicating that the cancellation request has been accepted. + */ + async cancel( + projectId: string, + activityId: string, + environmentId?: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkActivityId(activityId); + + if (!environmentId) { + return await this.prjActApi.actionProjectsActivitiesCancel({ projectId, activityId }); + } else { + TaskBase.checkEnvironmentId(environmentId); + return await this.envActApi.actionProjectsEnvironmentsActivitiesCancel({ + projectId, + environmentId, + activityId, + }); + } + } + + /** + * Get the details of an activity for a project or environment. + * @param projectId - The ID of the project. + * @param activityId - The ID of the activity to retrieve. + * @param environmentId - (Optional) The ID of the environment. If not provided, the activity is assumed to be a project-level activity. + * @returns The details of the specified activity. + */ + async get(projectId: string, activityId: string, environmentId?: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkActivityId(activityId); + + if (!environmentId) { + return await this.prjActApi.getProjectsActivities({ projectId, activityId }); + } else { + TaskBase.checkEnvironmentId(environmentId); + return await this.envActApi.getProjectsEnvironmentsActivities({ + projectId, + environmentId, + activityId, + }); + } + } + + /** + * List the activities for a project or environment. + * @param projectId - The ID of the project. + * @param environmentId - (Optional) The ID of the environment. If not provided, the activities for the entire project will be listed. + * @returns A list of activities for the specified project or environment. + */ + async list(projectId: string, environmentId?: string): Promise { + TaskBase.checkProjectId(projectId); + + if (!environmentId) { + return await this.prjActApi.listProjectsActivities({ projectId }); + } else { + TaskBase.checkEnvironmentId(environmentId); + return await this.envActApi.listProjectsEnvironmentsActivities({ projectId, environmentId }); + } + } + + /** + * Get the log output for an activity. + * @todo clarify this message as the activity.logs contains "Log for this activity is available in the streaming + * logs endpoint" + * @see https://linear.app/platformsh/issue/GIT-826/document-git-activity-log-endpoint-in-api-specs + * @param projectId - The ID of the project. + * @param activityId - The ID of the activity to retrieve logs for. + * @returns The log output for the specified activity. + */ + async log(projectId: string, activityId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkActivityId(activityId); + + throw new Error('Not implemented, prefere use get() (contains log)'); + } +} diff --git a/src/core/tasks/activity.ts b/src/core/tasks/activity.ts deleted file mode 100644 index 4ae401d..0000000 --- a/src/core/tasks/activity.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { EnvironmentActivityApi, ProjectActivityApi } from "../../apis-gen/index.js"; -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class ActivityTask extends TaskBase { - private prjApi: ProjectActivityApi; - private envApi: EnvironmentActivityApi - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.prjApi = new ProjectActivityApi(this.client.apiConfig); - this.envApi = new EnvironmentActivityApi(this.client.apiConfig); - } - - async cancel(projectId: string, activityId: string, environmentId: string = "") { - TaskBase.checkProjectId(projectId); - TaskBase.checkActivityId(activityId); - - if (environmentId) { - return await this.envApi.actionProjectsEnvironmentsActivitiesCancel({ projectId, environmentId, activityId }); - } else { - return await this.prjApi.actionProjectsActivitiesCancel({ projectId, activityId }); - } - } - - async get(projectId: string, activityId: string, environmentId: string = "") { - TaskBase.checkProjectId(projectId); - TaskBase.checkActivityId(activityId); - - if (environmentId) { - return await this.envApi.getProjectsEnvironmentsActivities({ projectId, environmentId, activityId }); - } else { - return await this.prjApi.getProjectsActivities({ projectId, activityId }); - } - } - - async list(projectId: string, environmentId: string = "") { - TaskBase.checkProjectId(projectId); - - if (environmentId) { - return await this.envApi.listProjectsEnvironmentsActivities({ projectId, environmentId }); - } else { - return await this.prjApi.listProjectsActivities({ projectId }); - } - - } - - async log(projectId: string, activityId: string) { - if (!projectId || !activityId) { - throw new Error("Project ID and Activity ID are required"); - } - - throw new Error("Not implemented, prefere use get() (containes log)"); - } - -} diff --git a/src/core/tasks/application.ts b/src/core/tasks/application.ts deleted file mode 100644 index 07b3e8a..0000000 --- a/src/core/tasks/application.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { DeploymentApi } from "../../apis-gen/index.js"; -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class ApplicationTask extends TaskBase { - private depApi: DeploymentApi; - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.depApi = new DeploymentApi(this.client.apiConfig); - } - - async get(projectId: string, environmentId: string, applicationId: string) { - TaskBase.checkProjectId(projectId); - TaskBase.checkEnvironmentId(environmentId); - TaskBase.checkApplicationId(applicationId); - - throw new Error("Not implemented"); - - } - - async list(projectId: string, environmentId: string) { - TaskBase.checkProjectId(projectId); - TaskBase.checkEnvironmentId(environmentId); - - throw new Error("Not implemented"); - - return await this.depApi.listProjectsEnvironmentsDeployments({ projectId, environmentId }); - } -} diff --git a/src/core/tasks/applications.ts b/src/core/tasks/applications.ts new file mode 100644 index 0000000..96c69b9 --- /dev/null +++ b/src/core/tasks/applications.ts @@ -0,0 +1,56 @@ +import { WebApplicationsValue } from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; + +export class ApplicationsTask extends TaskBase { + constructor(protected readonly client: UpsunClient) { + super(client); + } + + /** + * Get the configuration of web applications for an environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment. + * @param applicationId - The ID of the application to retrieve the configuration for. + * @returns The configuration details for the specified web application, or null if the application is not found in + * the current deployment. + * @throws An error if the project ID, environment ID, or application ID is invalid, + * or if there is an issue retrieving the deployment details. + */ + async configGet( + projectId: string, + environmentId: string, + applicationId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + TaskBase.checkApplicationId(applicationId); + + const webapps = await this.list(projectId, environmentId); + return webapps[applicationId] || null; + } + + /** + * List the configuration of web applications for an environment. This method retrieves the current deployment for the + * environment and returns the `webapps` property from the deployment details, which contains the configuration of all + * web applications for the environment. The returned object is a mapping of application IDs to their respective + * configuration details. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment. + * @returns A mapping of application IDs to their respective configuration details for the specified environment. + * @throws An error if the project ID or environment ID is invalid, + * or if there is an issue retrieving the deployment details. + */ + async list( + projectId: string, + environmentId: string, + ): Promise<{ [key: string]: WebApplicationsValue }> { + const currentDeployment = await this.client.environments.getDeployment( + projectId, + environmentId, + 'current', + ); + + return currentDeployment.webapps || {}; + } +} diff --git a/src/core/tasks/backup.ts b/src/core/tasks/backup.ts deleted file mode 100644 index 878b986..0000000 --- a/src/core/tasks/backup.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { EnvironmentBackupsApi } from "../../apis-gen/index.js"; -import { EnvironmentBackupInput } from "../../apis-gen/models/index.js"; -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class BackupTask extends TaskBase { - private bckApi: EnvironmentBackupsApi; - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.bckApi = new EnvironmentBackupsApi(this.client.apiConfig); - } - - async create(projectId: string, environmentId: string, safe: boolean = true) { - TaskBase.checkProjectId(projectId); - TaskBase.checkEnvironmentId(environmentId); - - return await this.bckApi.backupEnvironment({ projectId, environmentId, environmentBackupInput: { safe } as EnvironmentBackupInput }); - } - - async delete(projectId: string, environmentId: string, backupId: string) { - TaskBase.checkProjectId(projectId); - TaskBase.checkEnvironmentId(environmentId); - TaskBase.checkBackupId(backupId); - - return await this.bckApi.deleteProjectsEnvironmentsBackups({ projectId, environmentId, backupId }); - } - - async get(projectId: string, environmentId: string, backupId: string) { - TaskBase.checkProjectId(projectId); - TaskBase.checkEnvironmentId(environmentId); - TaskBase.checkBackupId(backupId); - - return await this.bckApi.getProjectsEnvironmentsBackups({ projectId, environmentId, backupId }); - } - - async list(projectId: string, environmentId: string) { - TaskBase.checkProjectId(projectId); - TaskBase.checkEnvironmentId(environmentId); - - return await this.bckApi.listProjectsEnvironmentsBackups({ projectId, environmentId }); - } - - async restore(projectId: string, environmentId: string, backupId: string) { - TaskBase.checkProjectId(projectId); - TaskBase.checkEnvironmentId(environmentId); - TaskBase.checkBackupId(backupId); - - throw new Error("Not implemented"); - - return await this.bckApi.restoreBackup({ - projectId, - environmentId, - backupId, - environmentRestoreInput: { - environmentName: environmentId, - branchFrom: null, - restoreCode: true, - restoreResources: true, - resources: null } }); - } -} diff --git a/src/core/tasks/backups.ts b/src/core/tasks/backups.ts new file mode 100644 index 0000000..3f9b537 --- /dev/null +++ b/src/core/tasks/backups.ts @@ -0,0 +1,140 @@ +import { EnvironmentBackupsApi } from '../../api/index.js'; +import { AcceptedResponse, Backup, Resources6InitEnum } from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; + +export class BackupsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private bckApi: EnvironmentBackupsApi, + ) { + super(client); + } + + /** + * Create a backup for an environment. + * By default, the backup will be created as a "safe" backup, which means that the backup process will attempt to + * minimize the impact on the environment's performance and availability. + * If set to false ("Live backup"), this leaves the environment running and open to connections during the backup. + * This reduces downtime, at the risk of backing up data in an inconsistent state. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment. + * @param isSafe - Whether to create a "safe" backup (default: true). + * @returns An AcceptedResponse indicating that the backup creation request has been accepted. + */ + async create( + projectId: string, + environmentId: string, + isSafe: boolean = true, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.bckApi.backupEnvironment({ + projectId, + environmentId, + environmentBackupInput: { safe: isSafe }, + }); + } + + /** + * Delete a backup for an environment. The API will return a 202 Accepted response if the deletion request has been + * accepted and is being processed. However, the client should check the backup's details to confirm whether the + * deletion was successful or not. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment. + * @param backupId - The ID of the backup to delete. + * @returns An AcceptedResponse indicating that the backup deletion request has been accepted. + */ + async delete( + projectId: string, + environmentId: string, + backupId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + TaskBase.checkBackupId(backupId); + + return await this.bckApi.deleteProjectsEnvironmentsBackups({ + projectId, + environmentId, + backupId, + }); + } + + /** + * Get the details of a backup for an environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment. + * @param backupId - The ID of the backup to retrieve. + * @returns The details of the specified backup. + */ + async get(projectId: string, environmentId: string, backupId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + TaskBase.checkBackupId(backupId); + + return await this.bckApi.getProjectsEnvironmentsBackups({ projectId, environmentId, backupId }); + } + + /** + * List the backups for an environment. The returned list is ordered by creation date, with the most recent backup + * appearing first in the list. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment. + * @returns A list of backups for the specified environment. + */ + async list(projectId: string, environmentId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.bckApi.listProjectsEnvironmentsBackups({ projectId, environmentId }); + } + + /** + * Restore an environment from a backup. The API will return a 202 Accepted response if the restoration request has + * been accepted and is being processed. However, the client should check the activity's details to confirm whether + * the restoration was successful or not. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment. + * @param backupId - The ID of the backup to restore from. + * @param restoreCode - Whether to restore the code (default: true). + * @param restoreResources - Whether to restore the resources (default: true). + * @param environmentName - (Optional) The name for the new environment that will be created as part of the + * restoration. If not provided, the restored environment will keep the same name as before. + * @param branchFrom - (Optional) The name of an existing branch to use as the source for the restored environment's + * code. This is only applicable if `restoreCode` is set to true. If not provided, the restored environment + * will use the code from the backup. + * @param init - (Optional) The initialization resources strategy in the restored environment. This is only + * applicable if `restoreResources` is set to true. If not provided, it defaults to + * `Resources6InitEnum.DEFAULT`. + * @returns An AcceptedResponse indicating that the environment restoration request has been accepted. + */ + async restore( + projectId: string, + environmentId: string, + backupId: string, + restoreCode: boolean = true, + restoreResources: boolean = true, + environmentName?: string, + branchFrom?: string, + init: Resources6InitEnum = Resources6InitEnum.DEFAULT, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + TaskBase.checkBackupId(backupId); + + return await this.bckApi.restoreBackup({ + projectId, + environmentId, + backupId, + environmentRestoreInput: { + restoreCode, + restoreResources, + environmentName: environmentName || null, + branchFrom: branchFrom || null, + resources: { init: init }, + }, + }); + } +} diff --git a/src/core/tasks/certificate.ts b/src/core/tasks/certificate.ts deleted file mode 100644 index 7b73c77..0000000 --- a/src/core/tasks/certificate.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { CertManagementApi } from "../../apis-gen/index.js"; -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class CertificateTask extends TaskBase { - private certApi: CertManagementApi; - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.certApi = new CertManagementApi(this.client.apiConfig); - } - - async add(projectId: string, certificate: string, key: string, chain: string[] = []) { - TaskBase.checkProjectId(projectId); - if (!certificate || !key) { - throw new Error("Certificate and key are required"); - } - - return await this.certApi.createProjectsCertificates({ - projectId, - certificateCreateInput: { - certificate, - key, - chain - }}); - } - - async delete(projectId: string, certificateId: string) { - TaskBase.checkProjectId(projectId); - TaskBase.checkCertificateId(certificateId); - - return await this.certApi.deleteProjectsCertificates({ - projectId, - certificateId - }); - } - - async get(projectId: string, certificateId: string) { - TaskBase.checkProjectId(projectId); - TaskBase.checkCertificateId(certificateId); - - return await this.certApi.getProjectsCertificates({ - projectId, - certificateId - }); - } - - async list(projectId: string) { - TaskBase.checkProjectId(projectId); - - return await this.certApi.listProjectsCertificates({ - projectId - }); - } -} diff --git a/src/core/tasks/certificates.ts b/src/core/tasks/certificates.ts new file mode 100644 index 0000000..7b5301f --- /dev/null +++ b/src/core/tasks/certificates.ts @@ -0,0 +1,115 @@ +import { CertManagementApi } from '../../api/index.js'; +import { + AcceptedResponse, + Certificate, + CertificateCollection, + CertificatePatch, +} from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { CertificateCreateParams } from '../model.js'; +import { TaskBase } from './task_base.js'; + +export class CertificatesTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private certApi: CertManagementApi, + ) { + super(client); + } + + /** + * Add a certificate to a project. The API will return a 202 Accepted response if the certificate creation request has + * been accepted and is being processed. However, the client should check the certificate's details to confirm whether + * the creation was successful or not. + * @param projectId - The ID of the project. + * @param certificate - The certificate to add, in PEM format. + * @param key - The private key for the certificate, in PEM format. + * @param params - (Optional) Additional parameters for the certificate creation, such as a name or description. + * @returns An AcceptedResponse indicating that the certificate creation request has been accepted. + * @throws An error if the project ID is invalid, or if the certificate or key is missing or invalid. + */ + async add( + projectId: string, + certificate: string, + key: string, + params?: CertificateCreateParams, + ): Promise { + TaskBase.checkProjectId(projectId); + + if (!certificate || !key) { + throw new Error('Certificate and key are required'); + } + + return await this.certApi.createProjectsCertificates({ + projectId, + certificateCreateInput: { certificate, key, ...params }, + }); + } + + /** + * Delete a certificate from a project. The API will return a 202 Accepted response if the deletion request has been + * accepted and is being processed. However, the client should check the certificate's details to confirm whether the + * deletion was successful or not. + * @param projectId - The ID of the project. + * @param certificateId - The ID of the certificate to delete. + * @returns An AcceptedResponse indicating that the certificate deletion request has been accepted. + * @throws An error if the project ID or certificate ID is invalid. + */ + async delete(projectId: string, certificateId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkCertificateId(certificateId); + + return await this.certApi.deleteProjectsCertificates({ projectId, certificateId }); + } + + /** + * Get the details of a certificate for a project. + * @param projectId - The ID of the project. + * @param certificateId - The ID of the certificate to retrieve. + * @returns The details of the specified certificate. + * @throws An error if the project ID or certificate ID is invalid, or if there is an issue retrieving the + * certificate details. + */ + async get(projectId: string, certificateId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkCertificateId(certificateId); + + return await this.certApi.getProjectsCertificates({ projectId, certificateId }); + } + + /** + * List the certificates for a project. + * @param projectId - The ID of the project. + * @returns A collection of certificates for the specified project. + * @throws An error if the project ID is invalid, or if there is an issue retrieving the certificates. + */ + async list(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.certApi.listProjectsCertificates({ projectId }); + } + + /** + * Update a certificate for a project. The API will return a 202 Accepted response if the update request has been + * accepted and is being processed. + * @param projectId - The ID of the project. + * @param certificateId - The ID of the certificate to update. + * @param params - The parameters to update for the certificate. + * @returns An AcceptedResponse indicating that the certificate update request has been accepted. + * @throws An error if the project ID or certificate ID is invalid. + */ + async update( + projectId: string, + certificateId: string, + params?: CertificatePatch, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkCertificateId(certificateId); + + return await this.certApi.updateProjectsCertificates({ + projectId, + certificateId, + certificatePatch: params || {}, + }); + } +} diff --git a/src/core/tasks/domain.ts b/src/core/tasks/domain.ts deleted file mode 100644 index 1843a55..0000000 --- a/src/core/tasks/domain.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { DomainManagementApi } from "../../apis-gen/index.js"; -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class DomainTask extends TaskBase { - private domApi: DomainManagementApi; - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.domApi = new DomainManagementApi(this.client.apiConfig); - } - - static checkDomainId(domainId: string) { - if (!domainId) { - throw new Error("Domain ID is required"); - } - } - - async add(projectId: string, domain: string, environmentId: string = "") { - TaskBase.checkProjectId(projectId); - if (!domain) { - throw new Error("Domain must be a non-empty string"); - } - - if (environmentId) { - return await this.domApi.createProjectsEnvironmentsDomains({ - projectId, - environmentId, - domainCreateInput: { - name: domain, - }}); - } else { - return await this.domApi.createProjectsDomains({ - projectId, - domainCreateInput: { - name: domain, - }}); - } - } - - async delete(projectId: string, domainId: string, environmentId: string = "") { - TaskBase.checkProjectId(projectId); - DomainTask.checkDomainId(domainId); - - if (environmentId) { - return await this.domApi.deleteProjectsEnvironmentsDomains({ - projectId, - environmentId, - domainId - }); - } else { - return await this.domApi.deleteProjectsDomains({ - projectId, - domainId - }); - } - } - - async get(projectId: string, domainId: string, environmentId: string = "") { - TaskBase.checkProjectId(projectId); - DomainTask.checkDomainId(domainId); - - if (environmentId) { - return await this.domApi.getProjectsEnvironmentsDomains({ - projectId, - environmentId, - domainId - }); - } else { - return await this.domApi.getProjectsDomains({ - projectId, - domainId - }); - } - } - - async list(projectId: string, environmentId: string = "") { - TaskBase.checkProjectId(projectId); - - if (environmentId) { - return await this.domApi.listProjectsEnvironmentsDomains({ - projectId, - environmentId - }); - } else { - return await this.domApi.listProjectsDomains({ - projectId - }); - } - } - - async update(projectId: string, arg1: string) { - throw new Error('Method not implemented.'); - } -} diff --git a/src/core/tasks/domains.ts b/src/core/tasks/domains.ts new file mode 100644 index 0000000..ac620d8 --- /dev/null +++ b/src/core/tasks/domains.ts @@ -0,0 +1,174 @@ +import { DomainManagementApi } from '../../api/index.js'; +import { AcceptedResponse, Domain, DomainCollection, DomainPatch } from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; + +export class DomainsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private domApi: DomainManagementApi, + ) { + super(client); + } + + /** + * Add a domain to a project or environment. The API will return a 202 Accepted response if the domain creation + * request has been accepted and is being processed. However, the client should check the domain's details to confirm + * whether the creation was successful or not. + * @param projectId - The ID of the project. + * @param domain - The domain name to add (e.g., "example.com"). + * @param attributes - (Optional) A key-value map of additional attributes to associate with the domain. + * @param isDefault - (Optional) Whether to set this domain as the default domain for the project or environment. + * If true, this domain will be used as the default domain for the project or environment, and any existing default + * domain will be unset. + * @param replacementFor - (Optional) The ID of an existing domain that this new domain is replacing. This can be used + * to indicate that the new domain is intended to replace an existing domain, which may help with tracking and + * management of domains over time. + * @param environmentId - (Optional) The ID of the environment to add the domain to. + * If not provided, the domain will be added at the project level. + * @returns An AcceptedResponse indicating that the domain creation request has been accepted. + * @throws An error if the project ID is invalid, if the domain name is missing or invalid, + * or if there is an issue with the API request. + */ + async add( + projectId: string, + domain: string, + attributes?: { [key: string]: string }, + isDefault?: boolean, + replacementFor?: string, + environmentId?: string, + ): Promise { + TaskBase.checkProjectId(projectId); + + if (!domain) { + throw new Error('Domain must be a non-empty string'); + } + + const domainCreateInput = { name: domain, attributes, isDefault, replacementFor }; + + if (!environmentId) { + return await this.domApi.createProjectsDomains({ projectId, domainCreateInput }); + } else { + TaskBase.checkEnvironmentId(environmentId); + return await this.domApi.createProjectsEnvironmentsDomains({ + projectId, + environmentId, + domainCreateInput, + }); + } + } + + /** + * Delete a domain from a project or environment. The API will return a 202 Accepted response if the deletion request + * has been accepted and is being processed. However, the client should check the domain's details to confirm whether + * the deletion was successful or not. + * @param projectId - The ID of the project. + * @param domainId - The ID of the domain to delete. + * @param environmentId - (Optional) The ID of the environment to delete the domain from. If not provided, the domain + * will be deleted from the project level. + * @returns An AcceptedResponse indicating that the domain deletion request has been accepted. + * @throws An error if the project ID or domain ID is invalid, or if there is an issue with the API request. + */ + async delete( + projectId: string, + domainId: string, + environmentId?: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkDomainId(domainId); + + if (!environmentId) { + return await this.domApi.deleteProjectsDomains({ projectId, domainId }); + } else { + TaskBase.checkEnvironmentId(environmentId); + return await this.domApi.deleteProjectsEnvironmentsDomains({ + projectId, + environmentId, + domainId, + }); + } + } + + /** + * Get the details of a domain for a project or environment. + * @param projectId - The ID of the project. + * @param domainId - The ID of the domain to retrieve. + * @param environmentId - (Optional) The ID of the environment to retrieve the domain from. If not provided, the + * domain will be retrieved from the project level. + * @return The details of the specified domain. + * @throws An error if the project ID or domain ID is invalid, or if there is an issue with the API request. + */ + async get(projectId: string, domainId: string, environmentId?: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkDomainId(domainId); + + if (!environmentId) { + return await this.domApi.getProjectsDomains({ projectId, domainId }); + } else { + TaskBase.checkEnvironmentId(environmentId); + return await this.domApi.getProjectsEnvironmentsDomains({ + projectId, + environmentId, + domainId, + }); + } + } + + /** + * List the domains for a project or environment. The returned list is ordered by creation date, with the most recent + * domain appearing first in the list. + * @param projectId - The ID of the project. + * @param environmentId - (Optional) The ID of the environment to list the domains for. + * If not provided, the domains for the entire project will be listed. + * @returns A list of domains for the specified project or environment. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async list(projectId: string, environmentId?: string): Promise { + TaskBase.checkProjectId(projectId); + + if (!environmentId) { + return await this.domApi.listProjectsDomains({ projectId }); + } else { + TaskBase.checkEnvironmentId(environmentId); + return await this.domApi.listProjectsEnvironmentsDomains({ projectId, environmentId }); + } + } + + /** + * Update a domain for a project or environment. The API will return a 202 Accepted response if the update request has + * been accepted and is being processed. However, the client should check the domain's details to confirm whether the + * update was successful or not. + * @param projectId - The ID of the project. + * @param domainId - The ID of the domain to update. + * @param params - The parameters to update for the domain. + * @param environmentId - (Optional) The ID of the environment to update the domain for. If not provided, the domain + * will be updated at the project level. + * @returns An AcceptedResponse indicating that the domain update request has been accepted. + * @throws An error if the project ID or domain ID is invalid, or if there is an issue with the API request. + */ + async update( + projectId: string, + domainId: string, + params?: DomainPatch, + environmentId?: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkDomainId(domainId); + + if (!environmentId) { + return await this.domApi.updateProjectsDomains({ + projectId, + domainId, + domainPatch: params || {}, + }); + } else { + TaskBase.checkEnvironmentId(environmentId); + return await this.domApi.updateProjectsEnvironmentsDomains({ + projectId, + environmentId, + domainId, + domainPatch: params || {}, + }); + } + } +} diff --git a/src/core/tasks/environment.ts b/src/core/tasks/environment.ts deleted file mode 100644 index 1fcd832..0000000 --- a/src/core/tasks/environment.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; -import { EnvironmentApi } from "../../apis-gen/index.js"; -import { - EnvironmentActivateInput, - EnvironmentMergeInput, - Resources1, - Resources1InitEnum, - Resources3, - Resources3InitEnum -} from "../../apis-gen/models/index.js"; -import { TaskBase } from "./taskBase.js"; - - -export class EnvironementTask extends TaskBase { - private envApi: EnvironmentApi; - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.envApi = new EnvironmentApi(this.client.apiConfig); - } - - async activate(projectId: string, env_name: string) { - const api = new EnvironmentApi(this.client.apiConfig); - return await api.activateEnvironment({ - projectId, - environmentId: env_name, - environmentActivateInput: { resources: { init: Resources1InitEnum.Default } as Resources1 } as EnvironmentActivateInput - }); - } - - // async branch(projectId: string, env_name_src: string, env_name_dst) { - // const api = new EnvironmentApi(this.client.apiConfig); - // return await api.branchEnvironment({ - // projectId, - // environmentId: env_name, - // environmentBranchInput: { - // title: env_name, - // name: env_name, - // cloneParent: true, - // type: "development", - // resources: { init: Resources3InitEnum.Manual } as Resources3 - // } as EnvironmentBranchInput }); - // } - - async deactivate(projectId: string, env_name: string) { - const api = new EnvironmentApi(this.client.apiConfig); - return await api.deactivateEnvironment({ projectId, environmentId: env_name }); - } - - async delete(projectId: string, env_name: string) { - const api = new EnvironmentApi(this.client.apiConfig); - return await api.deleteEnvironment({ projectId, environmentId: env_name }); - } - - async info(projectId: string, env_name: string) { - const api = new EnvironmentApi(this.client.apiConfig); - return await api.getEnvironment({ projectId, environmentId: env_name }); - } - - async list(projectId: string) { - const api = new EnvironmentApi(this.client.apiConfig); - return await api.listProjectsEnvironments({ projectId }); - } - - async logs(projectId: string, env_name: string, app_name: string) { - throw new Error("Not implemented"); - } - - async merge(projectId: string, env_name: string) { - const api = new EnvironmentApi(this.client.apiConfig); - return await api.mergeEnvironment({ - projectId, - environmentId: env_name, - environmentMergeInput: { resources: { init: Resources3InitEnum.Default } as Resources3 } as EnvironmentMergeInput - }); - } - - async pause(projectId: string, env_name: string) { - const api = new EnvironmentApi(this.client.apiConfig); - return await api.pauseEnvironment({ projectId, environmentId: env_name }) - } - - async relationships(projectId: string, env_name: string) { - throw new Error("Not implemented"); - } - - async redeploy(projectId: string, env_name: string) { - const api = new EnvironmentApi(this.client.apiConfig); - return await api.redeployEnvironment({ projectId, environmentId: env_name }) - } - - async resume(projectId: string, env_name: string) { - const api = new EnvironmentApi(this.client.apiConfig); - return await api.resumeEnvironment({ projectId, environmentId: env_name }) - } - - async urls(projectId: string, env_name: string) { - throw new Error("Not implemented"); - } - -} diff --git a/src/core/tasks/environments.ts b/src/core/tasks/environments.ts new file mode 100644 index 0000000..a84f0e1 --- /dev/null +++ b/src/core/tasks/environments.ts @@ -0,0 +1,886 @@ +import { UpsunClient } from '../../upsun.js'; +import { DeploymentApi, EnvironmentApi, EnvironmentTypeApi } from '../../api/index.js'; +import { + AcceptedResponse, + Activity, + Backup, + Deployment, + Domain, + DomainPatch, + Environment, + EnvironmentActivateInput, + EnvironmentBranchInputTypeEnum, + EnvironmentPatch, + EnvironmentType, + EnvironmentVariable, + FilesInner, + HttpAccessPermissions2, + Resources3InitEnum, + Resources4InitEnum, + Resources5InitEnum, + Resources6InitEnum, + Route, + RouteCollection, + ServiceRelationshipsValue, +} from '../../model/index.js'; +import { TaskBase } from './task_base.js'; +import { EnvironmentVariableCreateParams } from '../model.js'; + +export class EnvironmentsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private envApi: EnvironmentApi, + private envTypeApi: EnvironmentTypeApi, + private deployApi: DeploymentApi, + ) { + super(client); + } + + /** + * Activate an environment. The API will return a 202 Accepted response if the activation request has been accepted, + * but the client should check the environment's current activities to confirm whether the activation was successful + * or not. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to activate. + * @param init - (Optional) The initialization strategy to use when activating the environment. This can be used to + * specify whether to initialize the environment with code and/or data from the parent environment, and whether to + * rebase the environment. + * @return An AcceptedResponse indicating that the activation request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async activate( + projectId: string, + environmentId: string, + init?: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.activateEnvironment({ + projectId, + environmentId, + environmentActivateInput: { + resources: { init }, + } as EnvironmentActivateInput, + }); + } + + /** + * Create a new environment by branching from an existing environment. The new environment will be created + * asynchronously, and the API will return a 202 Accepted response if the branch request has been accepted. + * The client can then check the list of environments or the details of the new environment to monitor the progress + * and confirm when the branching is completed. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to branch from. + * @param title - The title for the new environment. This is a required parameter and must be a non-empty string. + * @param name - The name for the new environment. This is a required parameter and must be a non-empty string. + * The name must be unique within the project and can only contain lowercase letters, numbers, and hyphens. + * @param cloneParent - Whether to clone the code and data from the parent environment. + * @returns An AcceptedResponse indicating that the branch request has been accepted. + * @throws An error if the project ID or environment ID is invalid, if the title or name is missing or invalid, + * or if there is an issue with the API request. + */ + async branch( + projectId: string, + environmentId: string, + title: string, + name: string, + cloneParent: boolean = true, + type: EnvironmentBranchInputTypeEnum = EnvironmentBranchInputTypeEnum.DEVELOPMENT, + init: Resources3InitEnum = Resources3InitEnum.PARENT, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + if (!title) { + throw new Error('Title must be a non-empty string'); + } + + if (!name) { + throw new Error('Name must be a non-empty string'); + } + + return await this.envApi.branchEnvironment({ + projectId, + environmentId: environmentId, + environmentBranchInput: { title, name, cloneParent, type, resources: { init } }, + }); + } + + /** + * Deactivate an environment. The API will return a 202 Accepted response if the deactivation request has been + * accepted, but the client should check the environment's current activities to confirm whether the deactivation was + * successful or not. + * @param projectId the ID of the project. + * @param environmentId the ID of the environment to deactivate. + * @return An AcceptedResponse indicating that the deactivation request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async deactivate(projectId: string, environmentId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.deactivateEnvironment({ projectId, environmentId }); + } + + /** + * Delete an environment. The deletion will be best-effort and may not succeed if the environment is currently + * undergoing another activity such as deployment, merging, etc. The API will return a 202 Accepted response if + * the delete request has been accepted, but the client should check the environment's current activities to confirm + * whether the deletion was successful or not. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to delete. + * @return An AcceptedResponse indicating that the delete request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async delete(projectId: string, environmentId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.deleteEnvironment({ projectId, environmentId }); + } + + /** + * Update the HTTP access permissions for the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to update the HTTP access permissions for. + * @param httpAccess - The HTTP access permissions to set for the environment. + * @return An AcceptedResponse indicating that the update request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async httpAccess( + projectId: string, + environmentId: string, + httpAccess: HttpAccessPermissions2, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return this.update(projectId, environmentId, { httpAccess }); + } + + /** + * Get details of a specific environment. The details include information about the environment's current status. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to retrieve details for. + * @return The details of the specified environment. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async get(projectId: string, environmentId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.getEnvironment({ projectId, environmentId }); + } + + /** + * Get or Update details of the environment. If params are provided, the environment will be updated with the + * specified parameters before returning the details. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to retrieve or update details for. + * @param params - (Optional) The parameters to update for the environment. If not provided, the environment will not + * be updated and the current details will be returned. + * @return The details of the specified environment after applying any updates if params were provided. + * @throws An error if the project ID or environment ID is invalid, if there is an issue with the API request, or if + * the update request was provided but failed. + */ + async info( + projectId: string, + environmentId: string, + params?: EnvironmentPatch, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + if (params) { + await this.update(projectId, environmentId, params); + } + + return await this.get(projectId, environmentId); + } + + /** + * Initialize the environment by deploying code from a specified repository and profile, with optional configuration + * and initialization parameters. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to initialize. + * @param profile - The profile to use for initialization. + * @param repository - The repository to use for initialization. This should be in the format "owner/repo" for + * GitHub repositories. + * @param files - An array of files to include in the initialization. Each file should be represented as a tuple of + * [filePath, fileMode, fileContents], where filePath is the path to the file in the environment, fileMode is the + * file mode (e.g., "100644" for regular files), and fileContents is the content of the file as a string. + * @param config - (Optional) Additional configuration to use for initialization. This can be used to specify + * environment variables, routes, and other settings to apply during initialization. + * @param init - (Optional) The initialization strategy to use when initializing the environment. This can be used to + * specify whether to initialize the environment with code and/or data from the parent environment, and whether to + * rebase the environment. + * @return An AcceptedResponse indicating that the initialization request has been accepted. + * @throws An error if the project ID or environment ID is invalid, if the profile or repository is missing or + * invalid, if the files array is empty or contains invalid entries, or if there is an issue with the API request. + */ + async init( + projectId: string, + environmentId: string, + profile: string, + repository: string, + files: FilesInner[], + config?: string, + init: Resources4InitEnum = Resources4InitEnum.DEFAULT, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + if (!profile) { + throw new Error('Profile must be a non-empty string'); + } + if (!repository) { + throw new Error('Repository must be a non-empty string'); + } + + if (files.length === 0) { + throw new Error('Files must be a non-empty array of [filePath, fileMode, fileContents]'); + } + + return await this.envApi.initializeEnvironment({ + projectId, + environmentId, + environmentInitializeInput: { + profile, + repository, + config: config || null, + resources: { init }, + files, + }, + }); + } + + /** + * List all environments in a project. + * @param projectId - The ID of the project. + * @return A list of environments in the specified project. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async list(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.envApi.listProjectsEnvironments({ projectId: projectId }); + } + + //TODO implement logs streaming? + async logs(projectId: string, environmentId: string, app_name: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + throw new Error('Not implemented yet'); + } + + /** + * Merge the environment with its parent. The merge will be best-effort and may not succeed if the environment is + * currently undergoing another activity such as deployment, merging, etc. + * The API will return a 202 Accepted response if the merge request has been accepted, but the client should check + * the environment's current activities to confirm whether the merge was successful or not. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to merge. + * @param init - (Optional) The initialization strategy to use when merging the environment. This can be used to + * specify whether to initialize the environment with code and/or data from the parent environment, and whether to + * rebase the environment. + * @return An AcceptedResponse indicating that the merge request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async merge( + projectId: string, + environmentId: string, + init: Resources5InitEnum = Resources5InitEnum.DEFAULT, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.mergeEnvironment({ + projectId: projectId, + environmentId: environmentId, + environmentMergeInput: { resources: { init: init } }, + }); + } + + /** + * Pause the environment. The API will return a 202 Accepted response if the pause request has been accepted, + * but the client should check the environment's current activities to confirm whether the pause action was successful + * or not. + * @param projectId the ID of the project. + * @param environmentId the ID of the environment to pause. + * @return An AcceptedResponse indicating that the pause request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async pause(projectId: string, environmentId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.pauseEnvironment({ projectId, environmentId }); + } + + /** + * Redeploy the environment. Redeployment will trigger a new deployment activity on the environment, + * which will redeploy the currently deployed code without making any changes to the environment's code or + * configuration. The API will return a 202 Accepted response if the redeploy request has been accepted, + * but the client should check the environment's current activities to confirm whether the redeploy was successful + * or not. + * @param projectId the ID of the project. + * @param environmentId the ID of the environment to redeploy. + * @return An AcceptedResponse indicating that the redeploy request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async redeploy(projectId: string, environmentId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.redeployEnvironment({ projectId, environmentId }); + } + + /** + * Get the relationships of an environment, which include the linked applications or services. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to get relationships for. + * @param appId - The ID of the application to get relationships for. This is used to filter the relationships to only + * include those that are relevant to the specified application. + * @return The relationships of the environment for the specified application. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async relationships( + projectId: string, + environmentId: string, + appId: string, + ): Promise<{ [key: string]: ServiceRelationshipsValue }> { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + const appConfig = await this.client.applications.configGet(projectId, environmentId, appId); + + return appConfig.relationships; + } + + /** + * Resume an environment that is currently paused. The API will return a 202 Accepted response if the resume request + * has been accepted, but the client should check the environment's current activities to confirm whether the resume + * action was successful or not. + * @param projectId the ID of the project. + * @param environmentId the ID of the environment to resume. + * @return An AcceptedResponse indicating that the resume request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async resume(projectId: string, environmentId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.resumeEnvironment({ projectId, environmentId }); + } + + /** + * Synchronize the environment with its parent. The synchronization will be best-effort and may not succeed if the + * environment is currently undergoing another activity such as deployment, merging, etc. + * The API will return a 202 Accepted response if the synchronization request has been accepted, + * but the client should check the environment's current activities to confirm whether the synchronization was + * successful or not. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to synchronize. + * @param synchronizeCode Whether to synchronize the code from the parent environment. If false, the environment's + * code will not be changed during synchronization. + * @param rebase Whether to rebase the environment's code on top of the parent environment's code. If false, the + * environment's code will not be rebased. + * @param synchronizeData Whether to synchronize the data from the parent environment. If false, the environment's + * data will not be changed during synchronization. + * @param synchronizeResources Whether to synchronize the resources from the parent environment. If false, the + * environment's resources will not be changed during synchronization. + * @return An AcceptedResponse indicating that the synchronization request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async synchronize( + projectId: string, + environmentId: string, + synchronizeCode: boolean = true, + rebase: boolean = true, + synchronizeData: boolean = true, + synchronizeResources: boolean = true, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.synchronizeEnvironment({ + projectId: projectId, + environmentId: environmentId, + environmentSynchronizeInput: { + synchronizeCode, + rebase, + synchronizeData, + synchronizeResources, + }, + }); + } + + /** + * Update the environment with the specified parameters. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to update. + * @param params - The parameters to update for the environment. This can include changes to the environment's title, + * description, HTTP access permissions, and other settings. + * @return An AcceptedResponse indicating that the update request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async update( + projectId: string, + environmentId: string, + params?: EnvironmentPatch, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envApi.updateEnvironment({ + projectId, + environmentId, + environmentPatch: params || {}, + }); + } + + /** + * Cancel an ongoing activity on the environment, such as deployment, synchronization, etc. + * The cancellation will be best-effort and may not succeed if the activity is too close to completion. + * The API will return a 202 Accepted response if the cancellation request has been accepted, + * but the client should check the environment's current activities to confirm whether the cancellation was successful + * or not. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to cancel the activity on. + * @param activityId - The ID of the activity to cancel. + * @return An AcceptedResponse indicating that the cancellation request has been accepted. + * @throws An error if the project ID, environment ID, or activity ID is invalid, or if there is an issue with the + * API request. + */ + async activityCancel( + projectId: string, + environmentId: string, + activityId: string, + ): Promise { + return await this.client.activities.cancel(projectId, activityId, environmentId); + } + + /** + * Get details of a specific activity on the environment, such as deployment, synchronization, etc. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to get the activity details for. + * @param activityId - The ID of the activity to get details for. + * @return The details of the specified activity. + * @throws An error if the project ID, environment ID, or activity ID is invalid, or if there is an issue with the + * API request. + */ + async getActivity( + projectId: string, + environmentId: string, + activityId: string, + ): Promise { + return await this.client.activities.get(projectId, activityId, environmentId); + } + + /** + * List all activities on the environment, such as deployments, synchronizations, etc. + * @param projectId - the ID of the project. + * @param environmentId - the ID of the environment to list activities for. + * @return A list of activities on the specified environment. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async listActivities(projectId: string, environmentId: string): Promise { + return await this.client.activities.list(projectId, environmentId); + } + + /** + * Trigger a backup of the environment. The backup will be created asynchronously, and the API will return + * a 202 Accepted response if the backup request has been accepted. The client can then check the list of backups to + * monitor the progress and confirm when the backup is completed. + * The isSafe parameter is a best-effort attempt to create a backup without causing disruption to the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to back up. + * @param isSafe - Whether to attempt a safe backup that minimizes disruption to the environment. This is a + * best-effort attempt. + * @return An AcceptedResponse indicating that the backup request has been accepted. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async backup( + projectId: string, + environmentId: string, + isSafe?: boolean, + ): Promise { + return await this.client.backups.create(projectId, environmentId, isSafe); + } + + /** + * List all backups of the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to list backups for. + * @return A list of backups for the specified environment. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async listBackups(projectId: string, environmentId: string): Promise { + return await this.client.backups.list(projectId, environmentId); + } + + /** + * Delete a specific backup of the environment. The deletion will be best-effort and may not succeed if the backup is + * currently being created or restored. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment that the backup belongs to. + * @param backupId - The ID of the backup to delete. + * @return An AcceptedResponse indicating that the delete request has been accepted. + * @throws An error if the project ID, environment ID, or backup ID is invalid, or if there is an issue with the API + * request. + */ + async deleteBackup( + projectId: string, + environmentId: string, + backupId: string, + ): Promise { + return await this.client.backups.delete(projectId, environmentId, backupId); + } + + /** + * Get details of a specific backup of the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment that the backup belongs to. + * @param backupId - The ID of the backup to get details for. + * @return The details of the specified backup. + * @throws An error if the project ID, environment ID, or backup ID is invalid, or if there is an issue with the API + * request. + */ + async getBackup(projectId: string, environmentId: string, backupId: string): Promise { + return await this.client.backups.get(projectId, environmentId, backupId); + } + /** + * Restore the environment from a specific backup. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to restore. + * @param backupId - The ID of the backup to restore from. + * @param restoreCode - Whether to restore the code from the backup. If false, only the data and resources will be + * restored, and the environment's code will not be changed. + * @param restoreResources - Whether to restore the resources from the backup. If false, only the code and data will + * be restored, and the environment's resources will not be changed. + * @param environmentName - (Optional) The name for the new environment created from the backup. If not provided, the + * restored environment will keep the same name as before. + * @param branchFrom - (Optional) The ID of the environment to branch from when restoring. If provided, the restored + * environment will be created as a new branch from the specified environment instead of replacing the existing + * environment. This can be used to keep the existing environment intact while creating a new environment from the + * backup. + * @param init - (Optional) The initialization strategy to use when restoring the environment. This can be used to + * specify whether to initialize the environment with code and/or data from the backup, and whether to rebase the + * environment. + * @return An AcceptedResponse indicating that the restore request has been accepted. + * @throws An error if the project ID, environment ID, or backup ID is invalid, or if there is an issue with the API + * request. + */ + async restoreBackup( + projectId: string, + environmentId: string, + backupId: string, + restoreCode: boolean = true, + restoreResources: boolean = true, + environmentName?: string, + branchFrom?: string, + init?: Resources6InitEnum, + ): Promise { + return await this.client.backups.restore( + projectId, + environmentId, + backupId, + restoreCode, + restoreResources, + environmentName, + branchFrom, + init, + ); + } + + /** + * Get details of a specific environment type, such as development, production, etc. + * @param projectId - The ID of the project. + * @param environmentTypeId - The ID of the environment type to get details for. + * @return The details of the specified environment type. + * @throws An error if the project ID or environment type ID is invalid, or if there is an issue with the API request. + */ + async getType(projectId: string, environmentTypeId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentTypeId); + + return await this.envTypeApi.getEnvironmentType({ + projectId: projectId, + environmentTypeId: environmentTypeId, + }); + } + + /** + * Create an environment variable in the environment. Environment variables are used to store configuration values + * that can be accessed by the applications running in the environment. The name of the variable must be unique within + * the environment. If a variable with the same name already exists, the API will return an error. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to create the variable in. + * @param name - The name of the environment variable. This must be a non-empty string and unique within the + * environment. + * @param value - The value of the environment variable. This can be any string. + * @param params - (Optional) Additional parameters for creating the environment variable, such as whether the + * variable is secret or not. + * @return An AcceptedResponse indicating that the create variable request has been accepted. + * @throws An error if the project ID or environment ID is invalid, if the name is missing or invalid, if a variable + * with the same name already exists in the environment, or if there is an issue with the API request. + */ + async createVariables( + projectId: string, + environmentId: string, + name: string, + value: string, + params?: EnvironmentVariableCreateParams, + ): Promise { + return await this.client.variables.createEnvironmentVariable( + projectId, + environmentId, + name, + value, + params, + ); + } + + /** + * Delete an environment variable from the environment. The API will return an error if the variable does not exist. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to delete the variable from. + * @param variableId - The ID of the environment variable to delete. + * @return An AcceptedResponse indicating that the delete variable request has been accepted. + * @throws An error if the project ID, environment ID, or variable ID is invalid, if the variable does not exist in + * the environment, or if there is an issue with the API request. + */ + async deleteVariable( + projectId: string, + environmentId: string, + variableId: string, + ): Promise { + return await this.client.variables.deleteEnvironmentVariable( + projectId, + environmentId, + variableId, + ); + } + + /** + * Get details of a specific environment variable in the environment. + * The API will return an error if the variable does not exist. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to get the variable details from. + * @param variableId - The ID of the environment variable to get details for. + * @return The details of the specified environment variable. + * @throws An error if the project ID, environment ID, or variable ID is invalid, if the variable does not exist in + * the environment, or if there is an issue with the API request. + */ + async getVariable( + projectId: string, + environmentId: string, + variableId: string, + ): Promise { + return await this.client.variables.getEnvironmentVariable(projectId, environmentId, variableId); + } + + /** + * List all environment variables in the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to list variables for. + * @return A list of environment variables in the specified environment. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async listVariables(projectId: string, environmentId: string): Promise { + return await this.client.variables.listEnvironmentVariables(projectId, environmentId); + } + + /** + * Update an environment variable in the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to update the variable in. + * @param variableId - The ID of the environment variable to update. + * @param name - The new name for the environment variable. This must be a non-empty string and unique within the + * environment. If a variable with the same name already exists, the API will return an error. + * @param value - The new value for the environment variable. This can be any string. + * @param params - (Optional) Additional parameters for updating the environment variable, such as whether the + * variable is secret or not. + * @return An AcceptedResponse indicating that the update variable request has been accepted. + * @throws An error if the project ID, environment ID, or variable ID is invalid, if the name is missing or invalid, + * if a variable with the same name already exists in the environment, if the variable to update does not exist in the + * environment, or if there is an issue with the API request. + */ + async updateVariable( + projectId: string, + environmentId: string, + variableId: string, + name: string, + value: string, + params?: EnvironmentVariableCreateParams, + ): Promise { + return await this.client.variables.updateEnvironmentVariable( + projectId, + environmentId, + variableId, + name, + value, + params, + ); + } + + /** + * Get details of a specific route in the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to get the route details from. + * @param routeId - The ID of the route to get details for. + * @return The details of the specified route. + * @throws An error if the project ID, environment ID, or route ID is invalid, if the route does not exist in + * the environment, or if there is an issue with the API request. + */ + async getRoute(projectId: string, environmentId: string, routeId: string): Promise { + return await this.client.routes.get(projectId, environmentId, routeId); + } + + /** + * List all routes in the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to list routes for. + * @return A list of routes in the specified environment. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async listRoutes(projectId: string, environmentId: string): Promise { + return await this.client.routes.list(projectId, environmentId); + } + + /** + * Create a new route in the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to create the route in. + * @param path - The path for the route. This should be a valid URL path (e.g., "/api"). + * @param destination - The destination for the route. This should specify where traffic matching the route's path + * should be directed to (e.g., a specific application or service in the environment). + * @param isDefault - Whether this route should be the default route for the environment. If true, this route will + * be used to handle any traffic that does not match any other routes in the environment. + * @return An AcceptedResponse indicating that the create route request has been accepted. + * @throws An error if the project ID or environment ID is invalid, if the path or destination is missing or invalid, + * if a route with the same path already exists in the environment, or if there is an issue with the API request. + */ + async createDomain( + projectId: string, + environmentId: string, + domainName: string, + attributes?: Record, + isDefault?: boolean, + replacementFor?: string, + ): Promise { + return await this.client.domains.add( + projectId, + domainName, + attributes, + isDefault, + replacementFor, + environmentId, + ); + } + + /** + * Delete a domain from the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to delete the domain from. + * @param domainId - The ID of the domain to delete. + * @return An AcceptedResponse indicating that the delete domain request has been accepted. + * @throws An error if the project ID, environment ID, or domain ID is invalid, if the domain does not exist in + * the environment, or if there is an issue with the API request. + */ + async deleteDomain( + projectId: string, + environmentId: string, + domainId: string, + ): Promise { + return await this.client.domains.delete(projectId, domainId, environmentId); + } + + /** + * Get details of a specific domain in the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to get the domain details from. + * @param domainId - The ID of the domain to get details for. + * @return The details of the specified domain. + * @throws An error if the project ID, environment ID, or domain ID is invalid, if the domain does not exist in + * the environment, or if there is an issue with the API request. + */ + async getDomain(projectId: string, environmentId: string, domainId: string): Promise { + return await this.client.domains.get(projectId, domainId, environmentId); + } + + /** + * List all domains in the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to list domains for. + * @return A list of domains in the specified environment. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async listDomains(projectId: string, environmentId: string): Promise { + return await this.client.domains.list(projectId, environmentId); + } + + /** + * Update a domain in the environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to update the domain in. + * @param domainId - The ID of the domain to update. + * @param params - The parameters to update for the domain, such as the domain's attributes, whether it is the default + * domain, etc. + * @return An AcceptedResponse indicating that the update domain request has been accepted. + * @throws An error if the project ID, environment ID, or domain ID is invalid, if the domain to update does not exist + * in the environment, or if there is an issue with the API request. + */ + async updateDomain( + projectId: string, + environmentId: string, + domainId: string, + params?: DomainPatch, + ): Promise { + return await this.client.domains.update(projectId, domainId, params, environmentId); + } + + /** + * Get details of a specific deployment on the environment. Deployments represent the process of deploying code + * changes to the environment. The deployment details include information about the commit being deployed, the status + * of the deployment, and any associated activities or logs. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to get the deployment details from. + * @param deploymentId - The ID of the deployment to get details for. + * @return The details of the specified deployment. + * @throws An error if the project ID, environment ID, or deployment ID is invalid, if the deployment does not exist + * on the environment, or if there is an issue with the API request. + */ + async getDeployment( + projectId: string, + environmentId: string, + deploymentId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + TaskBase.checkDeploymentId(deploymentId); + + return await this.deployApi.getProjectsEnvironmentsDeployments({ + projectId, + environmentId, + deploymentId, + }); + } + + /** + * List all deployments on the environment. Deployments represent the process of deploying code changes to the + * environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to list deployments for. + * @return A list of deployments on the specified environment. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async listDeployments(projectId: string, environmentId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.deployApi.listProjectsEnvironmentsDeployments({ projectId, environmentId }); + } +} diff --git a/src/core/tasks/index.ts b/src/core/tasks/index.ts new file mode 100644 index 0000000..28503c6 --- /dev/null +++ b/src/core/tasks/index.ts @@ -0,0 +1,24 @@ +export * from './activities.js'; +export * from './applications.js'; +export * from './backups.js'; +export * from './certificates.js'; +export * from './domains.js'; +export * from './environments.js'; +export * from './integrations.js'; +export * from './metrics.js'; +export * from './mounts.js'; +export * from './operations.js'; +export * from './organizations.js'; +export * from './projects.js'; +export * from './repositories.js'; +export * from './resources.js'; +export * from './routes.js'; +export * from './services.js'; +export * from './source-operations.js'; +export * from './ssh.js'; +export * from './task_base.js'; +export * from './teams.js'; +export * from './users.js'; +export * from './users-invitations.js'; +export * from './variables.js'; +export * from './workers.js'; diff --git a/src/core/tasks/integrations.ts b/src/core/tasks/integrations.ts new file mode 100644 index 0000000..4ac7375 --- /dev/null +++ b/src/core/tasks/integrations.ts @@ -0,0 +1,136 @@ +import { ThirdPartyIntegrationsApi } from '../../api/index.js'; +import { AcceptedResponse, Integration, IntegrationCollection } from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { IntegrationCreateData } from '../model.js'; +import { TaskBase } from './task_base.js'; + +export class IntegrationsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private thirdPartyIntegrationsApi: ThirdPartyIntegrationsApi, + ) { + super(client); + } + + /** + * Create a third-party integration for a project. This method allows you to create a new integration for a project by + * specifying the type of integration and the necessary parameters for that integration. + * @param projectId - The ID of the project to create the integration for. + * @param type - The type of integration to create. This should be a valid integration type supported by the API. + * @param params - An object containing the necessary parameters for the integration. The specific parameters required + * will depend on the type of integration being created, and may include details such as authentication credentials, + * configuration options, and other relevant information. + * @return An AcceptedResponse indicating that the integration creation request has been accepted. The client should + * check the status of the integration through the integration details to confirm whether it was created successfully + * or if there were any issues. + * @throws An error if the project ID is invalid, if the integration type is not specified, or if there is an issue + * with the API request. + */ + async createIntegration( + projectId: string, + type: string, + params: IntegrationCreateData, + ): Promise { + TaskBase.checkProjectId(projectId); + + if (!type) { + throw new Error('Integration type is required'); + } + + return await this.thirdPartyIntegrationsApi.createProjectsIntegrations({ + projectId, + integrationCreateInput: { type, ...params }, + }); + } + + /** + * Delete a third-party integration from a project. This method allows you to delete an existing integration from a + * project. + * @param projectId - The ID of the project to delete the integration from. + * @param integrationId - The ID of the integration to delete. This should be a valid identifier for an integration + * that is associated with the specified project. + * @return An AcceptedResponse indicating that the integration deletion request has been accepted. The client should + * check the status of the integration through the integration details to confirm whether it was deleted successfully + * or if there were any issues. + * @throws An error if the project ID or integration ID is invalid, or if there is an issue with the API request. + */ + async deleteIntegration(projectId: string, integrationId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkIntegrationId(integrationId); + + return await this.thirdPartyIntegrationsApi.deleteProjectsIntegrations({ + projectId, + integrationId, + }); + } + + /** + * List all third-party integrations for a project. This method retrieves a list of all integrations that are + * associated with the specified project. + * @param projectId - The ID of the project to list integrations for. + * @return A list of integrations that are associated with the specified project, including details such as the + * integration type, configuration, and other relevant metadata. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listIntegrations(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.thirdPartyIntegrationsApi.listProjectsIntegrations({ projectId }); + } + + /** + * Get the details of a specific third-party integration for a project. This method retrieves the details of a + * specific integration that is associated with the specified project. + * @param projectId - The ID of the project to get the integration details for. + * @param integrationId - The ID of the integration to retrieve details for. This should be a valid identifier for an + * integration that is associated with the specified project. + * @return The details of the specified integration, including information such as the integration type, + * configuration, and other relevant metadata. + * @throws An error if the project ID or integration ID is invalid, or if there is an issue with the API request. + */ + async getIntegration(projectId: string, integrationId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkIntegrationId(integrationId); + + return await this.thirdPartyIntegrationsApi.getProjectsIntegrations({ + projectId, + integrationId, + }); + } + + /** + * Update an existing third-party integration for a project. This method allows you to update the configuration of an + * existing integration for a project by specifying the new parameters for that integration. + * @param projectId - The ID of the project to update the integration for. + * @param integrationId - The ID of the integration to update. This should be a valid identifier for an integration + * that is associated with the specified project. + * @param type - The type of integration to update. This should be a valid integration type supported by the API. + * @param params - An object containing the new parameters for the integration. The specific parameters required will + * depend on the type of integration being updated, and may include details such as authentication credentials, + * configuration options, and other relevant information. + * @return An AcceptedResponse indicating that the integration update request has been accepted. The client should + * check the status of the integration through the integration details to confirm whether it was updated successfully + * or if there were any issues. + * @throws An error if the project ID or integration ID is invalid, if the integration type is not specified, or if + * there is an issue with the API request. + */ + async updateIntegration( + projectId: string, + integrationId: string, + type: string, + params: IntegrationCreateData, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkIntegrationId(integrationId); + + if (!type) { + throw new Error('Integration type is required'); + } + + return await this.thirdPartyIntegrationsApi.updateProjectsIntegrations({ + projectId, + integrationId, + integrationPatch: { type, ...params }, + }); + } +} diff --git a/src/core/tasks/metrics.ts b/src/core/tasks/metrics.ts index cbd7517..e767bb3 100644 --- a/src/core/tasks/metrics.ts +++ b/src/core/tasks/metrics.ts @@ -1,13 +1,131 @@ -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; +import { UpsunClient } from '../../upsun.js'; +import { Metrics } from '../../model/index.js'; +import { TaskBase } from './task_base.js'; + +// Si fetch n'est pas disponible nativement, utiliser node-fetch ou globalThis.fetch export class MetricsTask extends TaskBase { - get(arg0: string, arg1: string, arg2: string): any { - throw new Error('Method not implemented.'); + async fetchMetrics(projectId: string, env_name: string, region: string): Promise { + const results: Metrics[] = []; + const url = `https://metrics-${projectId}.${region}.platformsh.site/v1/metrics/query`; + + const query = { + // "stream": { + // "collection": `vendor=platformsh/region=eu-3.platform.sh/project=${projectId}/environment=${env_name}`, + // "stream": "metrics" + // }, + // "range": { + // "from": "2025-09-29T12:25:02+02:00", + // "to": "2025-09-29T12:27:02+02:00" + // } + interval: '120s', + stream: { + collection: `vendor=platformsh/region=${region}.platform.sh/project=${projectId}/environment=${env_name}`, + stream: 'metrics', + }, + range: { + from: '2025-09-29T12:25:02+02:00', + to: '2025-09-29T12:27:02+02:00', + }, + fields: [ + { + name: 'cpu.max', + expr: '`cpu.cores`', + }, + // { + // "name": "memory.max", + // "expr": "`memory.limit`" + // }, + // { + // "name": "disk.value", + // "expr": "`disk.space.used`" + // }, + // { + // "name": "cpu.value", + // "expr": "SUM((`cpu.user` + `cpu.kernel`) / `interval`, 'service', 'instance')" + // }, + // { + // "name": "cpu.percentage", + // "expr": "100 * SUM((`cpu.user` + `cpu.kernel`) / (`interval` * `cpu.cores`), 'service', 'instance')" + // }, + + // { + // "name": "cpu.average.value", + // "expr": "AVG(SUM((`cpu.user` + `cpu.kernel`) / `interval`, 'service', 'instance'), 'service')" + // }, + // { + // "name": "cpu.average.percentage", + // "expr": "AVG(100 * SUM((`cpu.user` + `cpu.kernel`) / (`interval` * `cpu.cores`), 'service', 'instance'), 'service')" + // }, + // { + // "name": "memory.value", + // "expr": "SUM(`memory.apps` + `memory.kernel` + `memory.buffers`, 'service', 'instance')" + // }, + // { + // "name": "memory.percentage", + // "expr": "100 * SUM((`memory.apps` + `memory.kernel` + `memory.buffers`) / `memory.limit`, 'service', 'instance')" + // }, + + // { + // "name": "memory.average.value", + // "expr": "AVG(SUM(`memory.apps` + `memory.kernel` + `memory.buffers`, 'service', 'instance'), 'service')" + // }, + // { + // "name": "memory.average.percentage", + // "expr": "AVG(100 * SUM((`memory.apps` + `memory.kernel` + `memory.buffers`) / `memory.limit`, 'service', 'instance'), 'service')" + // }, + // { + // "name": "disk.percentage", + // "expr": "100 * (`disk.space.used`/`disk.space.limit`)" + // }, + // { + // "name": "disk.max", + // "expr": "AVG(`disk.space.limit`, 'mountpoint', 'service', 'instance')" + // }, + // { + // "name": "disk.average.value", + // "expr": "AVG(`disk.space.used`, 'mountpoint', 'service')" + // }, + // { + // "name": "disk.average.percentage", + // "expr": "AVG(100*(`disk.space.used`/`disk.space.limit`), 'mountpoint', 'service')" + // } + ], + }; + + const bearer = await this.client.getToken(); + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: bearer, + }, + body: JSON.stringify(query), + }); + if (!response.ok) { + throw new Error(`Fetch failed: ${response.status} ${response.statusText}`); + } + + // Hack because response is text/plain not application/json !! + // (not valid JSON because multiple JSON objects separated by new lines) + const text = await response.text(); + const texts = text.split('\n'); + texts.forEach((t, i) => { + try { + if (t.trim() !== '') { + const dto = JSON.parse(t); + results.push(dto); + } + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error parsing response:', error); + } + }); + + return results; } - + constructor(protected readonly client: UpsunClient) { super(client); } - } diff --git a/src/core/tasks/mount.ts b/src/core/tasks/mount.ts deleted file mode 100644 index aae1a87..0000000 --- a/src/core/tasks/mount.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class MountTask extends TaskBase { - - constructor(protected readonly client: UpsunClient) { - super(client); - } - - async download(projectId: string, mountId: string) { - throw new Error("Cannot be implemented"); - } - - async list(projectId: string) { - throw new Error("Cannot be implemented"); - } - - async upload(projectId: string, mountId: string) { - throw new Error("Cannot be implemented"); - } - -} diff --git a/src/core/tasks/mounts.ts b/src/core/tasks/mounts.ts new file mode 100644 index 0000000..55ed971 --- /dev/null +++ b/src/core/tasks/mounts.ts @@ -0,0 +1,59 @@ +import { MountsValue } from '../../model/MountsValue.js'; +import { UpsunClient } from '../../upsun.js'; +import { DeploymentResourceGroup } from '../model.js'; +import { TaskBase } from './task_base.js'; + +export class MountsTask extends TaskBase { + constructor(protected readonly client: UpsunClient) { + super(client); + } + + /** + * List the mounts for a specific project and resource type. + * This method retrieves the mounts for a specific project and resource type (webapps, services, or workers). + * It returns a record where the keys are the application names and the values are mount definitions associated + * with each application. + * @param projectId - The ID of the project to list mounts for. + * @param environmentId - The ID of the environment to list mounts for. This defaults to 'main' if not provided. + * @param filterType - The type of resource to list mounts for. This can be 'webapps', 'services', or 'workers'. If not + * provided, mounts for all resource types will be listed. + * @return A record where the keys are application names and the values are mount definitions associated with each + * application. If there are no mounts for the specified project and resource type, an empty record is returned. + * @throws An error if the project ID or resource type is invalid, or if there is an issue with the API request. + */ + async list( + projectId: string, + environmentId: string = 'main', + filterType?: DeploymentResourceGroup, + ): Promise> { + const currentDeployment = await this.client.environments.getDeployment( + projectId, + environmentId, + 'current', + ); + + const result: Record = {}; + const resourceTypes = filterType ? [filterType] : Object.values(DeploymentResourceGroup); + + for (const resourceType of resourceTypes) { + const group = currentDeployment[resourceType] ?? {}; + for (const app of Object.values(group)) { + const appName = app.name ?? app.id; + if (!appName) { + continue; + } + result[appName] = app.mounts ?? {}; + } + } + + return result; + } + + async download(projectId: string, mountId: string): Promise { + throw new Error('Cannot be implemented'); + } + + async upload(projectId: string, mountId: string, params: []): Promise { + throw new Error('Cannot be implemented'); + } +} diff --git a/src/core/tasks/operation.ts b/src/core/tasks/operation.ts deleted file mode 100644 index 50b81c2..0000000 --- a/src/core/tasks/operation.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class OperationTask extends TaskBase { - - constructor(protected readonly client: UpsunClient) { - super(client); - } - -} diff --git a/src/core/tasks/operations.ts b/src/core/tasks/operations.ts new file mode 100644 index 0000000..9627f16 --- /dev/null +++ b/src/core/tasks/operations.ts @@ -0,0 +1,66 @@ +import { AcceptedResponse, RuntimeOperationsApi } from '../../index.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; + +export class OperationsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private runApi: RuntimeOperationsApi, + ) { + super(client); + } + + /** + * Run an operation on a specific service in the environment. This allows you to execute predefined operations on + * services that are part of the current deployment. The operation is executed in the context of the specified deployment, + * which means it will have access to the environment variables and configuration of that deployment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to run the operation in. + * @param deploymentId - The ID of the deployment to run the operation in. This should be a specific deployment ID + * or 'current' to indicate the current deployment on the environment. + * @param service - The name of the service to run the operation on. This should be a service that is part of the + * current deployment. + * @param operation - The name of the operation to run. This should be a predefined operation that is supported by the + * specified service. + * @param parameters - An array of string parameters to pass to the operation. The specific parameters required will + * depend on the operation being executed. + * @return An AcceptedResponse indicating that the operation has been accepted for execution. The client should check + * the status of the operation through the activity details to confirm whether it was executed successfully or if + * there was an error. + */ + async run( + projectId: string, + environmentId: string, + deploymentId: string, + service: string, + operation: string, + parameters: string[], + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + TaskBase.checkDeploymentId(deploymentId); + + if (!service) { + throw new Error('Service must be a non-empty string'); + } + + if (!operation) { + throw new Error('Operation must be a non-empty string'); + } + + if (!parameters || parameters.length === 0) { + throw new Error('Parameters must be a non-empty array of strings'); + } + + return await this.runApi.runOperation({ + projectId, + environmentId, + deploymentId, + environmentOperationInput: { + service, + operation, + parameters, + }, + }); + } +} diff --git a/src/core/tasks/organization.ts b/src/core/tasks/organization.ts deleted file mode 100644 index 67b720b..0000000 --- a/src/core/tasks/organization.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { CreateOrgOperationRequest, ListUserOrgsRequest, OrganizationsApi } from "../../apis-gen/index.js"; -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class OrganizationTask extends TaskBase { - private orgApi: OrganizationsApi; - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.orgApi = new OrganizationsApi(this.client.apiConfig); - } - - async create(label: string, ownerId?: string, name?: string, country?: string ) { - return await this.orgApi.createOrg({ createOrgRequest: { ownerId, name, label, country } } as CreateOrgOperationRequest); - } - - async delete(organizationId: string) { - return await this.orgApi.deleteOrg({ organizationId }); - } - - async info(organizationId: string) { - return await this.orgApi.getOrg({ organizationId }); - } - - async list() { - return await this.orgApi.listUserOrgs({ userId: await this.client.getUserId()} as ListUserOrgsRequest); - } - -} diff --git a/src/core/tasks/organizations.ts b/src/core/tasks/organizations.ts new file mode 100644 index 0000000..fefe99a --- /dev/null +++ b/src/core/tasks/organizations.ts @@ -0,0 +1,897 @@ +import { + AddOnsApi, + EstimateNewOrgSubscriptionFormatEnum, + GetOrgOrderModeEnum, + InvoicesApi, + ListOrgInvoicesFilterStatusEnum, + ListOrgInvoicesFilterTypeEnum, + ListTeamsRequest, + MfaApi, + OrdersApi, + OrganizationMembersApi, + OrganizationsApi, + ProfilesApi, + RecordsApi, + SubscriptionsApi, + VouchersApi, +} from '../../api/index.js'; +import { + Address, + CanCreateNewOrgSubscription200Response, + CreateAuthorizationCredentials200Response, + CreateOrgRequestTypeEnum, + EstimationObject, + Invoice, + ListOrgInvoices200Response, + ListOrgMembers200Response, + ListOrgOrders200Response, + ListOrgPlanRecords200Response, + ListOrgProjects200Response, + ListOrgs200Response, + ListOrgSubscriptions200Response, + ListTeams200Response, + ListUserOrgs200Response, + Order, + Organization, + OrganizationAddonsObject, + OrganizationMember, + OrganizationMfaEnforcement, + Permissions, + Profile, + Project, + Subscription, + SubscriptionCurrentUsageObject, + UpdateOrgAddonsRequest, + UpdateOrgProfileRequest, + UpdateOrgRequest, +} from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; +import {} from './projects.js'; +import { + FilterListMembers, + FilterListOrders, + FilterListOrgProjects, + FilterListOrgs, + FilterListPlanRecords, + FilterListUsageRecords, + FilterListUser, + FilterListUserTeams, + ProjectCreateRequest, +} from '../model.js'; + +export class OrganizationsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private orgApi: OrganizationsApi, + private membersApi: OrganizationMembersApi, + private subApi: SubscriptionsApi, + private invApi: InvoicesApi, + private mfaApi: MfaApi, + private ordApi: OrdersApi, + private profApi: ProfilesApi, + private recApi: RecordsApi, + private vouchApi: VouchersApi, + private addOnsApi: AddOnsApi, + ) { + super(client); + } + + /** + * Create a new organization with the specified label and optional parameters such as type, owner ID, name, + * and country. + * @param label - The label for the new organization (required). + * @param type - The type of the organization (optional). This can be used to specify different types of + * organizations, such as "business", "personal", etc., depending on the API's supported organization types. + * @param ownerId - The ID of the user who will be the owner of the organization (optional). If not provided, the + * organization will be owned by the user making the API request. + * @param name - The name of the organization (optional). This can be a more descriptive name for the organization, + * in addition to the label. + * @param country - The country associated with the organization (optional). This can be used for localization or + * billing purposes, depending on the API's requirements. + * @return The details of the created organization. + * @throws An error if the label is missing or invalid, if any of the optional parameters are invalid, or if there is + * an issue with the API request. + */ + async create( + label: string, + type?: CreateOrgRequestTypeEnum, + ownerId?: string, + name?: string, + country?: string, + ): Promise { + if (!label) { + throw new Error('Label is required'); + } + + return await this.orgApi.createOrg({ + createOrgRequest: { + label, + type, + ownerId, + name, + country, + }, + }); + } + + /** + * Delete an organization by its ID. This will permanently delete the organization and all associated resources, so + * it should be used with caution. + * @param organizationId - The ID of the organization to delete. + */ + async delete(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.orgApi.deleteOrg({ organizationId }); + } + + /** + * Get the details of an organization by its ID, or update the organization if update parameters are provided. + * @param organizationId - The ID of the organization to get or update. + * @param updateOrgRequest - (Optional) The parameters to update the organization with. If provided, the organization + * will be updated with these parameters and the updated organization details will be returned. If not provided, the + * current organization details will be returned without making any changes. + * @return The details of the organization, either the current details if no update parameters are provided, or the + * updated details if update parameters are provided and the update is successful. + */ + async info(organizationId: string, updateOrgRequest?: UpdateOrgRequest): Promise { + TaskBase.checkOrganizationId(organizationId); + + if ( + updateOrgRequest && + (updateOrgRequest.country || + updateOrgRequest.label || + updateOrgRequest.name || + updateOrgRequest.securityContact) + ) { + return await this.update(organizationId, updateOrgRequest); + } else { + return await this.get(organizationId); + } + } + + /** + * Get the details of an organization by its ID. + * @param organizationId - The ID of the organization to retrieve. + * @return The details of the specified organization. + */ + async get(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.orgApi.getOrg({ organizationId }); + } + + /** + * Update an organization with the specified parameters. Only the parameters provided in the updateOrgRequest will be + * updated for the organization. For example, if only the label is provided in the updateOrgRequest, then only the + * label of the organization will be updated, and all other properties of the organization will remain unchanged. + * @param organizationId - The ID of the organization to update. + * @param updateOrgRequest - The parameters to update the organization with. Only the provided parameters will be + * updated. + * @returns The details of the updated organization. + */ + async update(organizationId: string, updateOrgRequest: UpdateOrgRequest): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.orgApi.updateOrg({ + organizationId, + updateOrgRequest, + }); + } + + /** + * List organizations with optional filtering. The filters can be used to narrow down the list of organizations based + * on specific criteria. + * @param filters - Optional filters to apply to the list of organizations. This can include criteria such as + * organization name, type, or owner ID. + * @return A list of organizations that match the specified filters. If no filters are provided, a list of all + * organizations accessible to the user will be returned. + */ + async list(filters?: FilterListOrgs): Promise { + return await this.orgApi.listOrgs(filters); + } + + /** + * List the subscriptions for an organization. This will return a list of all active and past subscriptions associated + * with the organization, including details such as the subscription plan, status, and billing information. + * @param organizationId - The ID of the organization to list subscriptions for. + * @return A list of subscriptions for the specified organization. + */ + async listSubscriptions(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.subApi.listOrgSubscriptions({ organizationId }); + } + + /** + * Add a member to an organization with the specified permissions. This will invite the user to join the organization, + * and the user will need to accept the invitation before they become an active member of the organization. + * The permissions parameter can be used to specify the level of access the member will have within the organization. + * @param organizationId - The ID of the organization to add the member to. + * @param userId - The ID of the user to add as a member of the organization. + * @param permissions - (Optional) The permissions to assign to the member within the organization. + * @returns The details of the added organization member, including their user ID, assigned permissions, + * and membership status. + */ + async addMember( + organizationId: string, + userId: string, + permissions?: Permissions, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkUserId(userId); + + return await this.membersApi.createOrgMember({ + organizationId, + createOrgMemberRequest: { userId, permissions: permissions }, + }); + } + + /** + * Delete a member from an organization. This will remove the user's membership from the organization, and they will + * no longer have access to the organization's resources. + * @param organizationId - The ID of the organization to remove the member from. + * @param userId - The ID of the user to remove from the organization. + */ + async deleteMember(organizationId: string, userId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkUserId(userId); + + await this.membersApi.deleteOrgMember({ organizationId, userId }); + } + + /** + * Get the details of an organization member by their user ID. This will return information about the member's + * membership in the organization, including their assigned permissions and membership status. + * @param organizationId - The ID of the organization to get the member from. + * @param userId - The ID of the user to retrieve as a member of the organization. + * @returns The details of the specified organization member, including their user ID, assigned permissions, and + * membership status. + */ + async getMember(organizationId: string, userId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkUserId(userId); + + return await this.membersApi.getOrgMember({ organizationId, userId }); + } + + /** + * List the members of an organization with optional filtering. + * @param organizationId - The ID of the organization to list members for. + * @param filters - Optional filters to apply to the list of members, such as filtering by user ID or permissions. + * @returns A list of organization members that match the specified filters. If no filters are provided, a list of all + * members of the organization will be returned. + * @throws An error if the organization ID is invalid, if the filters are invalid, or if there is an issue with the + * API request. + */ + async listMembers( + organizationId: string, + filters?: FilterListMembers, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.membersApi.listOrgMembers({ organizationId, ...filters }); + } + + /** + * Update an organization member's permissions. This will modify the member's access level within the organization + * based on the specified permissions. + * @param organizationId - The ID of the organization to update the member in. + * @param userId - The ID of the user whose membership is being updated. + * @param permissions - The new permissions to assign to the member within the organization. + * @returns The details of the updated organization member, including their user ID, assigned permissions, and + * membership status. + * @throws An error if the organization ID or user ID is invalid, if the permissions are invalid, or if there is an + * issue with the API request. + */ + async updateMember( + organizationId: string, + userId: string, + permissions?: string[], + ): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkUserId(userId); + + return await this.membersApi.updateOrgMember({ + organizationId, + userId, + updateOrgMemberRequest: { + permissions: permissions, + }, + }); + } + + /** + * List the organizations that a user belongs to, with optional filtering. This will return a list of organizations + * that the specified user is a member of, and the filters can be used to narrow down the list based on specific + * criteria. + * @param userId - The ID of the user to list organizations for. + * @param filters - Optional filters to apply to the list of organizations. + * @return A list of organizations that the specified user belongs to, matching the provided filters. + * + * @todo(@micka): check if this function needs to land in the usersTask or here? + */ + async listUserOrgs(userId: string, filters?: FilterListUser): Promise { + TaskBase.checkUserId(userId); + + return await this.orgApi.listUserOrgs({ userId, ...filters }); + } + + /** + * List organization accessible to the current user, with optional filtering. + * This will return a list of organizations that the current user has access to, and the filters can be used to narrow + * down the list based on specific criteria. + * @param filters - Optional filters to apply to the list of organizations. + * @return A list of organizations that the current user has access to, matching the provided filters. + */ + async listCurrentUserOrgs(filters?: FilterListUser): Promise { + return await this.listUserOrgs((await this.client.users.me()).id, filters); + } + + /** + * List teams within an organization, with optional filtering. This will return a list of teams that belong to the + * specified organization, and the filters can be used to narrow down the list based on specific criteria. + * @param params - Optional parameters to apply to the list of teams, such as filtering by team name or member count. + * @returns A list of teams within the organization that match the specified filters. If no filters are provided, a + * list of all teams within the organization will be returned. + * @throws An error if there is an issue with the API request or if the filters are invalid. + */ + async listTeams(params?: ListTeamsRequest): Promise { + return await this.client.teams.list(params || {}); + } + + /** + * Retrieves teams that the specified user is a member of. + * @param userId - The ID of the user to retrieve teams for. + * @param filters - Optional filters to apply to the list of teams. + * @returns A list of teams that the specified user is a member of, matching the provided filters. + * @throws An error if there is an issue with the API request or if the filters are invalid. + */ + async listTeamsByMember( + userId: string, + filters?: FilterListUserTeams, + ): Promise { + return await this.client.teams.listByMember(userId, filters); + } + + /** + * Get a project by its ID. This will return the details of the specified project. + * @param projectId - The ID of the project to retrieve. + * @return The details of the specified project. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async getProject(projectId: string): Promise { + return await this.client.projects.get(projectId); + } + + /** + * List projects within an organization, with optional filtering. This will return a list of projects that belong to + * the specified organization, and the filters can be used to narrow down the list based on specific criteria. + * @param organizationId - The ID of the organization to list projects for. + * @param filters - Optional filters to apply to the list of projects, such as filtering by project name or region. + * @return A list of projects within the organization that match the specified filters. If no filters are provided, a + * list of all projects within the organization will be returned. + * @throws An error if the organization ID is invalid, if the filters are invalid, or if there is an issue with the + * API request. + */ + async listProjects( + organizationId: string, + filters?: FilterListOrgProjects, + ): Promise { + return await this.client.projects.list(organizationId, filters); + } + + /** + * Check if a new project can be created within the specified organization. This will return information about whether + * the organization is eligible to create a new project, based on factors such as the organization's current + * subscription status, project limits, and any other relevant criteria defined by the API. + * @param organizationId - The ID of the organization to check for project creation eligibility. + * @return A response indicating whether a new project can be created within the organization, along with any relevant + * details or reasons if project creation is not allowed. + * @throws An error if the organization ID is invalid, or if there is an issue with the API request. + */ + async canCreateProject(organizationId: string): Promise { + return await this.client.projects.canCreate(organizationId); + } + + /** + * Create a new project within the specified organization, in the specified region, and with optional parameters such + * as project name and subscription plan. + * @param organizationId - The ID of the organization to create the project in. + * @param projectRegion - The region to create the project in. + * @param params - Optional parameters for the project creation, such as the project name and subscription plan. + * @return The details of the created project, including its ID, name, region, and subscription information. + * @throws An error if the organization ID is invalid, if the project region is invalid, if the parameters are + * invalid, or if there is an issue with the API request. + */ + async createProject( + organizationId: string, + projectRegion: string, + params?: ProjectCreateRequest, + ): Promise { + return await this.client.projects.create(organizationId, projectRegion, params); + } + + /** + * Delete a project by its ID. This will permanently delete the project and all associated resources, so it should be + * used with caution. + * @param projectId - The ID of the project to delete. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async deleteProject(projectId: string): Promise { + await this.client.projects.delete(projectId); + } + + /** + * Estimate the cost of creating a new project within the specified organization, based on parameters such as the + * number of environments, storage, and user licenses. + * @param organizationId - The ID of the organization to estimate the new project for. + * @param environments - The number of environments to include in the project (default is 3). + * @param storage - The amount of storage to include in the project, in GB (default is 500). + * @param userLicenses - The number of user licenses to include in the project (default is 1). + * @param format - (Optional) The format to return the estimation in, such as "detailed" or "summary". + * @return An estimation object containing the estimated cost and details of the new project based on the provided + * parameters. + */ + async estimateNewProject( + organizationId: string, + environments: number = 3, + storage: number = 500, + userLicenses: number = 1, + format?: EstimateNewOrgSubscriptionFormatEnum, + plan: string = 'upsun/flexible', + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.subApi.estimateNewOrgSubscription({ + organizationId, + environments, + storage, + userLicenses, + format, + plan: plan, + }); + } + + /** + * Estimate the cost of a project based on its current subscription and parameters such as the number of environments, + * storage, and user licenses. This can be used to get an estimate of the cost of the project if changes are made to + * its resources or subscription plan. + * @param organizationId - The ID of the organization that the project belongs to. + * @param projectId - The ID of the project to estimate the cost for. + * @param environments - The number of environments to include in the estimation (default is 3). + * @param storage - The amount of storage to include in the estimation, in GB (default is 500). + * @param userLicenses - The number of user licenses to include in the estimation (default is 1). + * @param format - (Optional) The format to return the estimation in, such as "detailed" or "summary". + * @return An estimation object containing the estimated cost and details of the project based on the provided + * parameters and its current subscription. + * @throws An error if the organization ID or project ID is invalid, if the parameters are invalid, or if there is an + * issue with the API request. + */ + async estimateProject( + organizationId: string, + projectId: string, + environments: number = 3, + storage: number = 500, + userLicenses: number = 1, + format?: EstimateNewOrgSubscriptionFormatEnum, + plan: string = 'upsun/flexible', + ): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkProjectId(projectId); + + const project = await this.getProject(projectId); + const subscriptionId = TaskBase.extractSubscriptionId(project.subscription.licenseUri); + TaskBase.checkSubscriptionId(subscriptionId); + + return await this.subApi.estimateOrgSubscription({ + organizationId, + subscriptionId, + plan: plan, + environments, + storage, + userLicenses, + format, + }); + } + + /** + * Get the current usage of a project based on its subscription, including details such as the number of environments, + * storage used, and user licenses in use. This can be used to monitor the project's resource usage and ensure it + * stays within the allocated limits. + * @param organizationId - The ID of the organization that the project belongs to. + * @param projectId - The ID of the project to get the usage for. + * @param usageGroups - (Optional) Specific usage groups to include in the response, such as "environments", + * "storage", or "userLicenses". + * @param includeNotCharged - (Optional) Whether to include usage that is not currently being charged for in the + * response. + * @return An object containing the current usage details of the project based on its subscription, including metrics + * such as the number of environments, storage used, and user licenses in use. + * @throws An error if the organization ID or project ID is invalid, if the parameters are invalid, or if there is an + * issue with the API request. + */ + async getProjectUsage( + organizationId: string, + projectId: string, + usageGroups?: string, + includeNotCharged?: boolean, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkProjectId(projectId); + + const project = await this.getProject(projectId); + const subscriptionId = TaskBase.extractSubscriptionId(project.subscription.licenseUri); + TaskBase.checkSubscriptionId(subscriptionId); + + return await this.subApi.getOrgSubscriptionCurrentUsage({ + organizationId, + subscriptionId, + usageGroups, + includeNotCharged, + }); + } + + /** + * Disable MFA enforcement for an organization. This will allow members of the organization to log in without being + * required to use multi-factor authentication (MFA). This should be used with caution, as it can reduce the security + * of the organization. + * @param organizationId - The ID of the organization to disable MFA enforcement for. + * @throws An error if the organization ID is invalid, or if there is an issue with the API request. + */ + async disableMfaEnforcement(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + await this.mfaApi.disableOrgMfaEnforcement({ organizationId }); + } + + /** + * Enable MFA enforcement for an organization. This will require all members of the organization to use multi-factor + * authentication (MFA) when logging in, which can enhance the security of the organization. + * @param organizationId - The ID of the organization to enable MFA enforcement for. + * @throws An error if the organization ID is invalid, or if there is an issue with the API request. + */ + async enableMfaEnforcement(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + await this.mfaApi.enableOrgMfaEnforcement({ organizationId }); + } + + /** + * Get the current MFA enforcement status for an organization. This will return information about whether MFA + * enforcement is enabled or disabled. + * @param organizationId - The ID of the organization to get the MFA enforcement status for. + * @return An object containing the current MFA enforcement status for the organization, indicating whether MFA + * enforcement is enabled or disabled. + * @throws An error if the organization ID is invalid, or if there is an issue with the API request. + */ + async getMfaEnforcement(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.mfaApi.getOrgMfaEnforcement({ organizationId }); + } + + /** + * Send MFA reminders to specified users within an organization. This can be used to prompt users to set up or use MFA + * if MFA enforcement is enabled for the organization and some users have not yet set up MFA or are not using it. + * @param organizationId - The ID of the organization to send MFA reminders for. + * @param userIds - A list of user IDs to send MFA reminders to. These should be users who are members of the + * organization and are expected to use MFA based on the organization's MFA enforcement settings. + * @throws An error if the organization ID is invalid, if the user IDs are invalid, or if there is an issue with the + * API request. + */ + async sendMfaReminders(organizationId: string, userIds: string[]): Promise { + TaskBase.checkOrganizationId(organizationId); + + await this.mfaApi.sendOrgMfaReminders({ + organizationId, + sendOrgMfaRemindersRequest: { + userIds, + }, + }); + } + + /** + * Get the details of an invoice by its ID for a specific organization. This will return information about the + * invoice, including the invoice amount, status, billing period, and any associated order or subscription details. + * @param invoiceId - The ID of the invoice to retrieve. + * @param organizationId - The ID of the organization that the invoice belongs to. + * @return The details of the specified invoice for the organization. + * @throws An error if the invoice ID or organization ID is invalid, or if there is an issue with the API request. + */ + async getInvoice(invoiceId: string, organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkInvoiceId(invoiceId); + + return await this.invApi.getOrgInvoice({ invoiceId, organizationId }); + } + + /** + * List the invoices for a specific organization, with optional filtering by status, type, or associated order ID. + * This will return a paginated list of invoices matching the specified criteria. + * @param organizationId - The ID of the organization to list invoices for. + * @param filterStatus - (Optional) Filter invoices by their status, such as "paid", "unpaid", "overdue", etc. + * @param filterType - (Optional) Filter invoices by their type, such as "subscription", "one-time", etc. + * @param filterOrderId - (Optional) Filter invoices by the associated order ID, to get invoices related to a specific + * order. + * @param page - (Optional) The page number to retrieve for paginated results (default is 1). + * @return A paginated list of invoices for the specified organization that match the provided filters. + * If no filters are provided, all invoices for the organization will be returned. + * @throws An error if the organization ID is invalid, if the filters are invalid, or if there is an issue with the + * API request. + */ + async listInvoices( + organizationId: string, + filterStatus?: ListOrgInvoicesFilterStatusEnum, + filterType?: ListOrgInvoicesFilterTypeEnum, + filterOrderId?: string, + page?: number, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.invApi.listOrgInvoices({ + organizationId, + filterStatus, + filterType, + filterOrderId, + page, + }); + } + + //TODO manage binaryResponse (blob?) + /** + * {{#responses}} + {{#isBinary}} + async {{operationId}}({{params}}): Promise { + const response = await this.request({ ... }); + return await response.arrayBuffer(); + } + {{/isBinary}} + {{^isBinary}} + async {{operationId}}({{params}}): Promise<{{returnType}}> { + // ...code normal... + } + {{/isBinary}} + {{/responses}} + */ + async downloadInvoice(token: string): Promise { + throw new Error('Method not implemented.'); + //return await this.ordApi.downloadInvoice({ token }); + } + + /** + * Create authorization credentials for a specific order within an organization. This will return credentials that + * can be used to authorize actions related to the order. + * @param organizationId - The ID of the organization that the order belongs to. + * @param orderId - The ID of the order to create authorization credentials for. + * @return The created authorization credentials for the specified order within the organization. + * @throws An error if the organization ID or order ID is invalid, or if there is an issue with the API request. + */ + async createAuthorizationCredentials( + organizationId: string, + orderId: string, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkOrderId(orderId); + + return await this.ordApi.createAuthorizationCredentials({ + organizationId, + orderId, + }); + } + + /** + * Get the details of an order by its ID for a specific organization. This will return information about the order, + * including the order status, items, total amount, and any associated invoice or subscription details. + * @param organizationId - The ID of the organization that the order belongs to. + * @param orderId - The ID of the order to retrieve. + * @param mode - (Optional) The mode to retrieve the order in, which can affect the level of detail or format of the + * returned order information. + * @return The details of the specified order for the organization. + * @throws An error if the organization ID or order ID is invalid, or if there is an issue with the API request. + */ + async getOrder( + organizationId: string, + orderId: string, + mode?: GetOrgOrderModeEnum, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkOrderId(orderId); + + return await this.ordApi.getOrgOrder({ organizationId, orderId, mode }); + } + + /** + * List the orders for a specific organization, with optional filtering by order status, date range, or associated + * subscription ID. This will return a paginated list of orders matching the specified criteria. + * @param organizationId - The ID of the organization to list orders for. + * @param filterStatus - (Optional) Filter orders by their status, such as "pending", "completed", "canceled", etc. + * @param filterStartDate - (Optional) Filter orders by a start date, to get orders created on or after this date. + * @param filterEndDate - (Optional) Filter orders by an end date, to get orders created on or before this date. + * @param filterSubscriptionId - (Optional) Filter orders by the associated subscription ID, to get orders related to a + * specific subscription. + * @param page - (Optional) The page number to retrieve for paginated results (default is 1). + * @return A paginated list of orders for the specified organization that match the provided filters. If no filters + * are provided, all orders for the organization will be returned. + * @throws An error if the organization ID is invalid, if the filters are invalid, or if there is an issue with the + * API request. + */ + async listOrders( + organizationId: string, + filters: FilterListOrders, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.ordApi.listOrgOrders({ organizationId, ...filters }); + } + + /** + * Get the address details for a specific organization. This will return information about the organization's address, + * including fields such as street, city, state, postal code, and country. + * @param organizationId - The ID of the organization to get the address for. + * @return The address details for the specified organization. + * @throws An error if the organization ID is invalid, or if there is an issue with the API request. + */ + async getAddress(organizationId: string): Promise
{ + TaskBase.checkOrganizationId(organizationId); + + return await this.profApi.getOrgAddress({ organizationId }); + } + + /** + * Get the profile details for a specific organization. This will return information about the organization's profile, + * including fields such as name, description, contact information, and other relevant details. + * @param organizationId - The ID of the organization to get the profile for. + * @return The profile details for the specified organization. + * @throws An error if the organization ID is invalid, or if there is an issue with the API request. + */ + async getProfile(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.profApi.getOrgProfile({ organizationId }); + } + + /** + * Update the address details for a specific organization. This will modify the organization's address information + * based on the provided address object. + * @param organizationId - The ID of the organization to update the address for. + * @param address - The new address details to update for the organization, including fields such as street, city, + * state, postal code, and country. + * @return The updated address details for the organization after the update is applied. + * @throws An error if the organization ID is invalid, if the address details are invalid, or if there is an issue + * with the API request. + */ + async updateAddress(organizationId: string, address: Address): Promise
{ + TaskBase.checkOrganizationId(organizationId); + + return await this.profApi.updateOrgAddress({ organizationId, address }); + } + + /** + * Update the profile details for a specific organization. This will modify the organization's profile information + * based on the provided profile object. + * @param organizationId - The ID of the organization to update the profile for. + * @param profile - The new profile details to update for the organization, including fields such as name, + * description, contact information, and other relevant details. + * @return The updated profile details for the organization after the update is applied. + * @throws An error if the organization ID is invalid, if the profile details are invalid, or if there is an issue + * with the API request. + */ + async updateProfile(organizationId: string, profile?: UpdateOrgProfileRequest): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.profApi.updateOrgProfile({ + organizationId, + updateOrgProfileRequest: profile, + }); + } + + /** + * List the plan records for a specific organization, with optional filtering by date range, record type, or + * associated subscription ID. This will return a paginated list of plan records matching the specified criteria. + * @param organizationId - The ID of the organization to list plan records for. + * @param filters - Optional filters to apply to the list of plan records, such as filtering by date range, record + * type, or associated subscription ID. + * @return A paginated list of plan records for the specified organization that match the provided filters. If no + * filters are provided, all plan records for the organization will be returned. + * @throws An error if the organization ID is invalid, if the filters are invalid, or if there is an issue with the + * API request. + */ + async listRecords( + organizationId: string, + filters: FilterListPlanRecords, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.recApi.listOrgPlanRecords({ organizationId, ...filters }); + } + + /** + * List the usage records for a specific organization, with optional filtering by date range, usage type, or + * associated subscription ID. This will return a paginated list of usage records matching the specified criteria. + * @param organizationId - The ID of the organization to list usage records for. + * @param filters - Optional filters to apply to the list of usage records, such as filtering by date range, usage + * type, or associated subscription ID. + * @return A paginated list of usage records for the specified organization that match the provided filters. If no + * filters are provided, all usage records for the organization will be returned. + * @throws An error if the organization ID is invalid, if the filters are invalid, or if there is an issue with the + * API request. + */ + async listUsageRecords( + organizationId: string, + filters: FilterListUsageRecords, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.recApi.listOrgUsageRecords({ organizationId, ...filters }); + } + + /** + * Apply a voucher code to an organization. This will attempt to apply the specified voucher code to the + * organization's account, which may result in discounts, credits, or other benefits being applied to the + * organization's subscription. + * @param organizationId - The ID of the organization to apply the voucher to. + * @param code - The voucher code to apply to the organization. This should be a valid voucher code that is eligible + * for use. + * @throws An error if the organization ID is invalid, if the voucher code is invalid or ineligible, or if there is + * an issue with the API request. + */ + async applyVoucher(organizationId: string, code: string): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkVoucherCode(code); + + await this.vouchApi.applyOrgVoucher({ + organizationId, + applyOrgVoucherRequest: { code: code }, + }); + } + + /** + * List the vouchers that have been applied to an organization. This will return a list of vouchers that are currently + * applied to the organization's account, along with details about each voucher such as the code, discount amount, + * expiration date, and any associated benefits or restrictions. + * @param organizationId - The ID of the organization to list vouchers for. + * @return A list of vouchers that have been applied to the specified organization, including details about each + * voucher. + * @throws An error if the organization ID is invalid, or if there is an issue with the API request. + */ + async listVouchers(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.vouchApi.listOrgVouchers({ organizationId }); + } + + /** + * Get the add-ons that are currently enabled for a specific organization. This will return a list of add-ons that are + * currently active for the organization, along with details about each add-on such as its name, description, and any + * associated benefits or features that it provides to the organization. + * @param organizationId - The ID of the organization to get add-ons for. + * @return A list of add-ons that are currently enabled for the specified organization, including details about each + * add-on. + * @throws An error if the organization ID is invalid, or if there is an issue with the API request. + */ + async getAddons(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.addOnsApi.getOrgAddons({ organizationId }); + } + + /** + * Update the add-ons for a specific organization. This will modify the organization's enabled add-ons based on the + * provided add-ons object, which may include enabling new add-ons or disabling existing ones. The response will + * return the updated list of add-ons that are currently enabled for the organization after the update is applied. + * @param organizationId - The ID of the organization to update add-ons for. + * @param addons - The add-ons details to update for the organization, including which add-ons to enable or disable. + * @return The updated list of add-ons that are currently enabled for the organization after the update is applied. + * @throws An error if the organization ID is invalid, if the add-ons details are invalid, or if there is an issue + * with the API request. + */ + async updateAddons( + organizationId: string, + addons: UpdateOrgAddonsRequest, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.addOnsApi.updateOrgAddons({ organizationId, updateOrgAddonsRequest: addons }); + } +} diff --git a/src/core/tasks/project.ts b/src/core/tasks/project.ts deleted file mode 100644 index aeab550..0000000 --- a/src/core/tasks/project.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; -import { ProjectApi, SubscriptionsApi } from "../../apis-gen/index.js"; -import { TaskBase } from "./taskBase.js"; - -export class ProjectTask extends TaskBase { - private prjApi: ProjectApi; - private subApi: SubscriptionsApi; - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.prjApi = new ProjectApi(this.client.apiConfig); - this.subApi = new SubscriptionsApi(this.client.apiConfig); - } - - async clearBuildCache(projectId: string) { - return await this.prjApi.actionProjectsClearBuildCache({ projectId }); - } - - async create(organizationId: string, projectRegion: string, projectTitle: string, - plan: string = "upsun/flexible", - defaultBranch: string = "main", - environmentCount: number = 2, - storage: number = 5) { - return await this.subApi.createOrgSubscription({ - organizationId, - createOrgSubscriptionRequest: { - plan, - projectRegion, - projectTitle, - defaultBranch, - environments: environmentCount, - storage - }, - }); - } - - async delete(projectId: string) { - return await this.prjApi.deleteProjects({ projectId }); - } - - async get(projectId: string) { - return await this.prjApi.getProjects({ projectId }); - } - - async getSubscription(organizationId: string, subscriptionId: string) { - return await this.subApi.getOrgSubscription({organizationId, subscriptionId }); - } - - async info(projectId: string) { - return await this.prjApi.getProjects({ projectId }); - } - - async list(organizationId: string) { - return await this.subApi.listOrgSubscriptions({ organizationId }); - } - -} diff --git a/src/core/tasks/projects.ts b/src/core/tasks/projects.ts new file mode 100644 index 0000000..8d3da46 --- /dev/null +++ b/src/core/tasks/projects.ts @@ -0,0 +1,901 @@ +import { UpsunClient } from '../../upsun.js'; +import { + ListProjectTeamAccessRequest, + ListTeamProjectAccessRequest, + OrganizationProjectsApi, + ProjectApi, + ProjectSettingsApi, + RepositoryApi, + SubscriptionsApi, + SystemInformationApi, +} from '../../api/index.js'; +import { + AcceptedResponse, + Activity, + CanCreateNewOrgSubscription200Response, + EnvironmentVariableCreateInput, + Project, + ProjectCapabilities, + ProjectPatch, + ProjectSettings, + ProjectVariable, + Subscription, + Domain, + Certificate, + TeamProjectAccess, + GrantProjectTeamAccessRequestInner, + GrantTeamProjectAccessRequestInner, + ListProjectTeamAccess200Response, + DomainPatch, + UserProjectAccess, + GrantProjectUserAccessRequestInner, + ListProjectUserAccess200Response, + Environment, + ProjectInvitation, + ListOrgProjects200Response, +} from '../../model/index.js'; +import { TaskBase } from './task_base.js'; +import { + CertificateCreateParams, + CreateProjectInvite, + FilterListOrgProjects, + FilterListProjectUserAccess, + FilterListUserProjectAccess, + ProjectCreateRequest, +} from '../model.js'; + +export class ProjectsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private prjApi: ProjectApi, + private orgPrjApi: OrganizationProjectsApi, + private subApi: SubscriptionsApi, + private settingsApi: ProjectSettingsApi, + ) { + super(client); + } + + /** + * Clears the build cache for a project. + * @param projectId - The ID of the project to clear the build cache for. + * @return An AcceptedResponse indicating that the request to clear the build cache has been accepted. + * The client should check the status of the operation through the activity details to confirm whether it was executed + * successfully or if there was an error. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async clearBuildCache(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.prjApi.actionProjectsClearBuildCache({ projectId }); + } + + /** + * Creates a new project subscription under the specified organization with the given parameters. + * @param organizationId - The ID of the organization to create the project subscription under. + * @param projectRegion - The region where the project will be created. This should be a valid region identifier + * where the project will be hosted. + * @param params - Optional parameters for creating the project subscription, such as the subscription plan, billing + * cycle, and any additional configuration options that may be required for the subscription. + * @return The details of the created subscription, including information such as the subscription ID, status, plan, + * and other relevant details. + * @throws An error if the organization ID is invalid, if the project region is invalid, if the parameters are + * invalid, or if there is an issue with the API request. + */ + async create( + organizationId: string, + projectRegion: string, + params?: ProjectCreateRequest, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkProjectRegion(projectRegion); + + return await this.subApi.createOrgSubscription({ + organizationId, + createOrgSubscriptionRequest: { projectRegion, ...params }, + }); + } + + /** + * Checks if a new project subscription can be created under the specified organization. This method is used to verify + * whether the organization is eligible to create a new project subscription based on factors such as the + * organization's current subscription status, limits, and any other relevant criteria. + * @param organizationId - The ID of the organization to check for project subscription creation eligibility. + * @return A response indicating whether a new project subscription can be created under the specified organization, + * along with any relevant details or reasons if the creation is not allowed. + */ + async canCreate(organizationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.subApi.canCreateNewOrgSubscription({ organizationId }); + } + + /** + * Deletes a project subscription. This will effectively delete the project associated with the subscription, along + * with any related resources and data. + * @param projectId - The ID of the project to delete. + * @return A promise that resolves when the project deletion request has been accepted. The client should check the + * status of the operation through the activity details to confirm whether the deletion was executed successfully or + * if there was an error. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async delete(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + const project = await this.prjApi.getProjects({ projectId }); + //TODO Why not using Project.subscription.id directly? FHK: Because it's empty + const subscriptionId = TaskBase.extractSubscriptionId(project.subscription.licenseUri); + TaskBase.checkSubscriptionId(subscriptionId); + + return await this.subApi.deleteOrgSubscription({ + organizationId: project.organization as string, + subscriptionId, + }); + } + + /** + * Get or update a project. + * @param projectId - The ID of the project to retrieve or update. + * @param params - Optional parameters to update the project with. If provided, the project will be updated with these + * parameters and the updated project details will be returned. If not provided, the current project details will be + * returned without any modifications. + * @return The details of the project after applying any updates if parameters were provided, or the current project + * details if no updates were made. + * @throws An error if the project ID is invalid, if the parameters are invalid, or if there is an issue with the API + * request. + */ + async info(projectId: string, params?: ProjectPatch): Promise { + TaskBase.checkProjectId(projectId); + + if (params && Object.keys(params).length > 0) { + return await this.update(projectId, params); + } else { + return await this.prjApi.getProjects({ projectId }); + } + } + + /** + * Get the details of a project by its ID. + * @param projectId - The ID of the project to retrieve. + * @return The details of the specified project. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async get(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.prjApi.getProjects({ projectId }); + } + + /** + * Update the details of a project. This allows you to modify the project's information such as its name, description, + * or other attributes that can be updated. The method will return the updated project details after applying the + * changes. + * @param projectId - The ID of the project to update. + * @param params - The parameters to update the project with. This should include the fields that you want to modify + * and their new values. + * @return The details of the project after applying the updates. + * @throws An error if the project ID is invalid, if the parameters are invalid, or if there is an issue with the API + * request. + */ + async update(projectId: string, params: ProjectPatch): Promise { + TaskBase.checkProjectId(projectId); + + await this.prjApi.updateProjects({ projectId, projectPatch: params }); + return await this.get(projectId); + } + + /** + * List the projects for an organization. This method retrieves a list of projects that belong to the specified + * organization, with optional filtering based on criteria such as project name, creation date, or other attributes. + * The returned list includes the details of each project that matches the specified filters. + * @param organizationId - The ID of the organization to list projects for. + * @param filters - Optional filters to apply to the list of projects. + * @return A list of projects that belong to the specified organization and match the provided filters. + * @throws An error if the organization ID is invalid, if the filters are invalid, or if there is an issue with the + * API request. + */ + async list( + organizationId: string, + filters?: FilterListOrgProjects, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.orgPrjApi.listOrgProjects({ organizationId, ...filters }); + } + + // Add more project-related methods as needed + + /** + * Get the subscription details for a project. This method retrieves the subscription information associated with the + * project, including details such as the subscription ID, status, plan, and other relevant information about the + * subscription that is linked to the project. + * @param projectId - The ID of the project to retrieve the subscription details for. + * @return The subscription details associated with the specified project. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async getSubscription(organizationId: string, subscriptionId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkSubscriptionId(subscriptionId); + + return await this.subApi.getOrgSubscription({ organizationId, subscriptionId }); + } + + /** + * Retrieves the capabilities that are available for the specified project. + * @param projectId - The ID of the project to retrieve capabilities for. + * @return The capabilities that are available for the specified project. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async getCapabilities(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.prjApi.getProjectsCapabilities({ projectId }); + } + + /** + * Cancel an invitation to a project. This will revoke the access that was granted to the invitee through the + * invitation, and the invite will no longer be valid. + * @param projectId - The ID of the project to cancel the invitation for. + * @param invitationId - The ID of the invitation to cancel. + * @return A promise that resolves when the invitation has been canceled. + * @throws An error if the project ID or invitation ID is invalid, or if there is an issue with the API request. + */ + async cancelInvite(projectId: string, inviteId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkInviteId(inviteId); + + await this.client.invitations.cancelProjectInvite(projectId, inviteId); + } + + /** + * Create an invitation to a project for a specified email address, with the specified role and permissions. + * @param projectId - The ID of the project to create the invitation for. + * @param email - The email address to send the invitation to. + * @param params - The parameters for the project invitation, including the role to assign to the invitee and any + * specific permissions to grant within the project. + * @return The details of the created project invitation. + * @throws An error if the project ID is invalid, if the email address is invalid, if the parameters are invalid, or + * if there is an issue with the API request. + */ + async createInvite( + projectId: string, + email: string, + params: CreateProjectInvite, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEmail(email); + + return await this.client.invitations.createProjectInvite(projectId, email, params); + } + + /** + * List all invitations for a project. + * @param projectId - The ID of the project to list invitations for. + * @return A list of project invitations. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listInvites(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.client.invitations.listProjectInvites(projectId); + } + + /** + * Get project settings. + * @param projectId - The ID of the project to retrieve settings for. + * @return The settings of the specified project. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async getSettings(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.settingsApi.getProjectsSettings({ projectId }); + } + + /** + * Update project settings. + * @param projectId - The ID of the project to update settings for. + * @param settings - The new settings to apply to the project. + * @return An AcceptedResponse indicating that the request to update the project settings has been accepted. + * The client should check the status of the update to confirm when it has been applied. + * @throws An error if the project ID is invalid, if the settings are invalid, or if there is an issue with the API + * request. + */ + async updateSettings(projectId: string, settings: ProjectSettings): Promise { + TaskBase.checkProjectId(projectId); + + return await this.settingsApi.updateProjectsSettings({ + projectId, + projectSettingsPatch: settings, + }); + } + + /** + * Create a new project variable. This allows you to add a new variable to the project, which can be used for + * configuration, secrets, or other purposes within the project. The method will return an AcceptedResponse indicating + * that the request to create the variable has been accepted, and the client should check the status of the operation + * to confirm when the variable has been created and is available for use. + * @param projectId - The ID of the project to create the variable for. + * @param name - The name of the variable to create. This should be a unique identifier for the variable within the + * project. + * @param value - The value of the variable to create. This can be any string value that you want to associate with + * the variable. + * @param params - Optional parameters for creating the variable, such as whether the variable is protected, masked, + * or other attributes. + * @return An AcceptedResponse indicating that the request to create the variable has been accepted. The client should + * check the status of the operation to confirm when the variable has been created and is available for use. + * @throws An error if the project ID is invalid, if the name or value is invalid, if the parameters are invalid, or + * if there is an issue with the API request. + */ + async createVariable( + projectId: string, + name: string, + value: string, + params?: EnvironmentVariableCreateInput, + ): Promise { + TaskBase.checkProjectId(projectId); + + return await this.client.variables.createProjectVariable(projectId, name, value, params); + } + + /** + * Get the details of a project variable by its ID. + * @param projectId - The ID of the project to retrieve the variable from. + * @param variableId - The ID of the variable to retrieve. + * @return The details of the specified project variable. + * @throws An error if the project ID or variable ID is invalid, or if there is an issue with the API request. + */ + async getVariable(projectId: string, variableId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkVariableId(variableId); + + return await this.client.variables.getProjectVariable(projectId, variableId); + } + + /** + * Delete a project variable by its ID. This will remove the variable from the project, and it will no longer be + * available for use within the project. The method will return a promise that resolves when the deletion request has + * been accepted, and the client should check the status of the operation to confirm when the variable has been + * deleted. + * @param projectId - The ID of the project to delete the variable from. + * @param variableId - The ID of the variable to delete. + * @return A promise that resolves when the deletion request has been accepted. The client should check the status of + * the operation to confirm when the variable has been deleted. + * @throws An error if the project ID or variable ID is invalid, or if there is an issue with the API request. + */ + async deleteVariable(projectId: string, variableId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkVariableId(variableId); + + return await this.client.variables.deleteProjectVariable(projectId, variableId); + } + + /** + * List all project variables for a specified project. This method retrieves a list of all variables that are + * associated with the specified project, including their details such as name, value, and any attributes. + * The returned list includes the details of each variable that belongs to the project. + * @param projectId - The ID of the project to list variables for. + * @return A list of project variables that belong to the specified project. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listVariables(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.client.variables.listProjectVariables(projectId); + } + + /** + * Update a project variable by its ID. This allows you to modify the value or attributes of an existing variable + * within the project. The method will return an AcceptedResponse indicating that the request to update the variable + * has been accepted, and the client should check the status of the operation to confirm when the variable has been + * updated and the changes have been applied. + * @param projectId - The ID of the project to update the variable in. + * @param variableId - The ID of the variable to update. + * @param params - The new parameters to apply to the variable, such as a new value or updated attributes. + * @return An AcceptedResponse indicating that the request to update the variable has been accepted. The client should + * check the status of the operation to confirm when the variable has been updated and the changes have been applied. + * @throws An error if the project ID or variable ID is invalid, if the parameters are invalid, or if there is an + * issue with the API request. + */ + async updateVariable( + projectId: string, + variableId: string, + params?: EnvironmentVariableCreateInput, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkVariableId(variableId); + + return await this.client.variables.updateProjectVariable(projectId, variableId, params); + } + + /** + * List all activities for a project. This method retrieves a list of all activities that have occurred within the + * specified project, including details such as the type of activity, the user who performed it, the timestamp, and + * any relevant metadata. + * @param projectId - The ID of the project to list activities for. + * @return A list of activities that have occurred within the specified project. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listActivities(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.client.activities.list(projectId); + } + + /** + * Get the details of a specific activity by its ID within a project. This method retrieves the details of a + * particular activity, including information such as the type of activity, the user who performed it, the timestamp, + * and any relevant metadata. + * @param projectId - The ID of the project to retrieve the activity from. + * @param activityId - The ID of the activity to retrieve. + * @return The details of the specified activity within the project. + * @throws An error if the project ID or activity ID is invalid, or if there is an issue with the API request. + */ + async getActivity(projectId: string, activityId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkActivityId(activityId); + + return await this.client.activities.get(projectId, activityId); + } + + // //TODO(@micka) do we expose it? seems that it's not public endpoint + // async createDeployment( + // projectId: string, + // type: DedicatedDeploymentTargetCreateInputTypeEnum, + // name: string, + // enforcedMounts?: object + // ): Promise { + // TaskBase.checkProjectId(projectId); + + // return await this.deploymentTargetApi.createProjectsDeployments({ + // projectId, + // deploymentTargetCreateInput: {type, name, enforcedMounts} + // }); + // } + + // async deleteDeployment(projectId: string, deploymentId: string): Promise { + // TaskBase.checkProjectId(projectId); + // TaskBase.checkDeploymentId(deploymentId); + + // return await this.deploymentTargetApi.deleteProjectsDeployments({ + // projectId, + // deploymentTargetConfigurationId: deploymentId + // }); + // } + + // async getDeployment(projectId: string, deploymentId: string): Promise { + // TaskBase.checkProjectId(projectId); + // TaskBase.checkDeploymentId(deploymentId); + + // return await this.deploymentTargetApi.getProjectsDeployments({ + // projectId, + // deploymentTargetConfigurationId: deploymentId + // }); + // } + + // async listDeployments(projectId: string): Promise { + // TaskBase.checkProjectId(projectId); + + // return await this.deploymentTargetApi.listProjectsDeployments({ projectId }); + // } + + // async updateDeployment( + // projectId: string, + // deploymentId: string, + // type: DedicatedDeploymentTargetCreateInputTypeEnum, + // name: string, + // enforcedMounts?: object + // ): Promise { + // TaskBase.checkProjectId(projectId); + // TaskBase.checkDeploymentId(deploymentId); + + // return await this.deploymentTargetApi.updateProjectsDeployments({ + // projectId, + // deploymentTargetConfigurationId: deploymentId, + // deploymentTargetPatch: { type, name, enforcedMounts } + // }); + // } + + /** + * Add a custom domain to a project. This allows you to associate a custom domain name with the project, which can be + * used to access the project. + * @param projectId - The ID of the project to add the domain to. + * @param domain - The custom domain name to add to the project. This should be a valid domain name that you want to + * associate with the project. + * @param attributes - Optional attributes to associate with the domain, such as SSL configuration, CNAME records, or + * other relevant settings for the domain. + * @param isDefault - Optional flag indicating whether this domain should be set as the default domain for the + * project. If true, this domain will be used as the primary domain for accessing the project. If false or not + * provided, the domain will be added but not set as the default. + * @param replacementFor - Optional ID of an existing domain that this new domain should replace. If provided, the new + * domain will take over the role of the specified existing domain, and the existing domain will be removed or + * deactivated as part of the process. This is useful for smoothly transitioning from one domain to another without + * downtime. + * @return An AcceptedResponse indicating that the request to add the domain has been accepted. The client should + * check the status of the operation to confirm when the domain has been added and is available for use. + * @throws An error if the project ID is invalid, if the domain name is invalid, if the attributes are invalid, or if + * there is an issue with the API request. + */ + async addDomain( + projectId: string, + domain: string, + attributes?: { [key: string]: string }, + isDefault?: boolean, + replacementFor?: string, + ): Promise { + return await this.client.domains.add(projectId, domain, attributes, isDefault, replacementFor); + } + + /** + * Delete a custom domain from a project. This will remove the association of the specified domain with the project, + * and the domain will no longer be used to access the project. + * @param projectId - The ID of the project to delete the domain from. + * @param domainId - The ID of the domain to delete from the project. This should be a valid identifier for a domain + * that is associated with the project. + * @return A promise that resolves when the domain deletion request has been accepted. The client should check the + * status of the operation to confirm when the domain has been deleted and is no longer available for use. + * @throws An error if the project ID or domain ID is invalid, or if there is an issue with the API request. + */ + async deleteDomain(projectId: string, domainId: string): Promise { + return await this.client.domains.delete(projectId, domainId); + } + + /** + * Get the details of a custom domain associated with a project by its ID. This method retrieves the information about + * a specific domain that is linked to the project. + * @param projectId - The ID of the project to retrieve the domain from. + * @param domainId - The ID of the domain to retrieve. This should be a valid identifier for a domain that is + * associated with the project. + * @return A promise that resolves to the details of the specified domain. + * @throws An error if the project ID or domain ID is invalid, or if there is an issue with the API request. + */ + async getDomain(projectId: string, domainId: string): Promise { + return await this.client.domains.get(projectId, domainId); + } + + /** + * List all custom domains associated with a project. This method retrieves a list of all domains that are linked to + * the project. + * @param projectId - The ID of the project to list domains for. + * @return A list of custom domains that are associated with the specified project, including details such as the + * domain name, attributes, and status. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listDomains(projectId: string): Promise { + return await this.client.domains.list(projectId); + } + + /** + * Update the details of a custom domain associated with a project. This allows you to modify the attributes or + * settings of an existing domain that is linked to the project. The method will return an AcceptedResponse indicating + * that the update request has been accepted and is being processed. + * @param projectId - The ID of the project to update the domain in. + * @param domainId - The ID of the domain to update. This should be a valid identifier for a domain that is associated + * with the project. + * @param params - The new parameters to apply to the domain, such as updated attributes, SSL configuration, or other + * settings that you want to modify for the domain. + * @return An AcceptedResponse indicating that the request to update the domain has been accepted. The client should + * check the status of the operation to confirm when the domain has been updated and the changes have been applied. + * @throws An error if the project ID or domain ID is invalid, if the parameters are invalid, or if there is an issue + * with the API request. + */ + async updateDomain( + projectId: string, + domainId: string, + params?: DomainPatch, + ): Promise { + return await this.client.domains.update(projectId, domainId, params); + } + + /** + * Add a custom SSL certificate to a project. This allows you to associate an SSL certificate with the project, which + * can be used to secure the custom domains that are linked to the project. + * @param projectId - The ID of the project to add the certificate to. + * @param certificate - The SSL certificate to add to the project. This should be a valid SSL certificate in PEM + * format. + * @returns An AcceptedResponse indicating that the request to add the certificate has been accepted. The client + * should check the status of the operation to confirm when the certificate has been added and the changes have been + * applied. + * @throws An error if the project ID is invalid, if the certificate is invalid, or if there is an issue with the API + * request. + */ + async addCertificate( + projectId: string, + certificate: string, + key: string, + params?: CertificateCreateParams, + ): Promise { + return await this.client.certificates.add(projectId, certificate, key, params); + } + + /** + * Delete a custom SSL certificate from a project. This will remove the association of the specified certificate with + * the project. + * @param projectId - The ID of the project to delete the certificate from. + * @param certificateId - The ID of the certificate to delete from the project. This should be a valid identifier for + * a certificate that is associated with the project. + * @return A promise that resolves when the certificate deletion request has been accepted. The client should check + * the status of the operation to confirm when the certificate has been deleted and the changes have been applied. + * @throws An error if the project ID or certificate ID is invalid, or if there is an issue with the API request. + */ + async deleteCertificate(projectId: string, certificateId: string): Promise { + return await this.client.certificates.delete(projectId, certificateId); + } + + /** + * Get the details of a custom SSL certificate associated with a project by its ID. This method retrieves the + * information about a specific SSL certificate that is linked to the project, including details such as the + * certificate name, expiration date, associated domains, and any relevant metadata. + * @param projectId - The ID of the project to retrieve the certificate from. + * @param certificateId - The ID of the certificate to retrieve. This should be a valid identifier for a certificate + * that is associated with the project. + * @return A promise that resolves to the details of the specified certificate. + * @throws An error if the project ID or certificate ID is invalid, or if there is an issue with the API request. + */ + async getCertificate(projectId: string, certificateId: string): Promise { + return await this.client.certificates.get(projectId, certificateId); + } + + /** + * List all custom SSL certificates associated with a project. This method retrieves a list of all SSL certificates + * that are linked to the project. + * @param projectId - The ID of the project to list certificates for. + * @return A list of custom SSL certificates that are associated with the specified project, including details such + * as the certificate name, expiration date, associated domains, and any relevant metadata. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listCertificates(projectId: string): Promise { + return await this.client.certificates.list(projectId); + } + + /** + * Get the access details of a team to a project. This method retrieves the access information for a specific team in + * relation to a project, including the level of access granted to the team, the permissions they have, and any + * relevant metadata about the team's access to the project. + * @param projectId - The ID of the project to retrieve the team access for. + * @param teamId - The ID of the team to retrieve access details for. This should be a valid identifier for a team + * that is associated with the project. + * @return The access details of the specified team to the project, including the level of access, permissions, and + * any relevant metadata. + * @throws An error if the project ID or team ID is invalid, or if there is an issue with the API request. + */ + async getTeamProjectAccessByProject( + projectId: string, + teamId: string, + ): Promise { + return await this.client.teams.getTeamProjectAccessByProject(projectId, teamId); + } + + /** + * Get the access details of a project to a team. This method retrieves the access information for a specific project + * in relation to a team, including the level of access granted to the project, the permissions it has, and any + * relevant metadata about the project's access to the team. + * @param teamId - The ID of the team to retrieve the project access for. + * @param projectId - The ID of the project to retrieve access details for. This should be a valid identifier for a + * project that is associated with the team. + * @return The access details of the specified project to the team, including the level of access, permissions, and + * any relevant metadata. + * @throws An error if the team ID or project ID is invalid, or if there is an issue with the API request. + */ + async getTeamProjectAccessByTeam(teamId: string, projectId: string): Promise { + return await this.client.teams.getTeamProjectAccessByTeam(teamId, projectId); + } + + /** + * Grant access to a project for a team. This method allows you to grant a specific level of access to a project for a + * team, along with any relevant permissions. The access details will be defined in the request body, and once the + * request is accepted, the team will have the specified access to the project. + * @param projectId - The ID of the project to grant access to. + * @param teamId - The ID of the team to grant access for. This should be a valid identifier for a team that is + * associated with the project. + * @param access - The access details to grant to the team for the project, including the level of access, + * permissions, and any relevant metadata. + * @return An AcceptedResponse indicating that the request to grant access has been accepted. The client should check + * the status of the request to confirm that the access has been granted. + * @throws An error if the project ID or team ID is invalid, if the access details are invalid, or if there is an + * issue with the API request. + */ + async grantTeamProjectAccessToProject( + projectId: string, + access: GrantProjectTeamAccessRequestInner[], + ): Promise { + return await this.client.teams.grantTeamProjectAccessToProject(projectId, access); + } + + /** + * Grant access to a team for a project. This method allows you to grant a specific level of access to a team for a + * project, along with any relevant permissions. The access details will be defined in the request body, and once the + * request is accepted, the project will have the specified access to the team. + * @param teamId - The ID of the team to grant access to. + * @param access - The access details to grant to the project for the team, including the level of access, + * permissions, and any relevant metadata. + * @return An AcceptedResponse indicating that the request to grant access has been accepted. The client should check + * the status of the request to confirm that the access has been granted. + * @throws An error if the team ID is invalid, if the access details are invalid, or if there is an issue with the API + * request. + */ + async grantTeamProjectAccessToTeam( + teamId: string, + access: GrantTeamProjectAccessRequestInner[], + ): Promise { + return await this.client.teams.grantTeamProjectAccessToTeam(teamId, access); + } + + /** + * List the access details of all teams to a project. This method retrieves a list of all teams that have access to a + * project, along with the access details for each team, including the level of access, permissions, and any relevant + * metadata about their access to the project. + * @param projectId - The ID of the project to list team access for. + * @param params - Optional parameters to filter or paginate the list of team access details. + * @return A list of team access details for all teams that have access to the specified project, including the level + * of access, permissions, and any relevant metadata. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listTeamProjectAccessByProject( + projectId: string, + params: ListProjectTeamAccessRequest, + ): Promise { + return await this.client.teams.listTeamProjectAccessByProject(projectId, params); + } + + /** + * List the access details of all projects to a team. This method retrieves a list of all projects that a team has + * access to, along with the access details for each project, including the level of access, permissions, and any + * relevant metadata about their access to the project. + * @param teamId - The ID of the team to list project access for. + * @param params - Optional parameters to filter or paginate the list of project access details. + * @return A list of project access details for all projects that the specified team has access to, including the + * level of access, permissions, and any relevant metadata. + * @throws An error if the team ID is invalid, or if there is an issue with the API request. + */ + async listTeamProjectAccessByTeam( + teamId: string, + params: ListTeamProjectAccessRequest, + ): Promise { + return await this.client.teams.listTeamProjectAccessByTeam(teamId, params); + } + + /** + * Revoke access to a project for a team. This method allows you to revoke the access that a team has to a project, + * which will remove the team's permissions and access to the project. Once the request is accepted, the team will no + * longer have access to the project. + * @param projectId - The ID of the project to revoke access from. + * @param teamId - The ID of the team to revoke access for. This should be a valid identifier for a team that is + * associated with the project. + * @return An AcceptedResponse indicating that the request to revoke access has been accepted. The client should check + * the status of the request to confirm that the access has been revoked. + * @throws An error if the project ID or team ID is invalid, or if there is an issue with the API request. + */ + async revokeTeamProjectAccessByProject(projectId: string, teamId: string): Promise { + return await this.client.teams.revokeTeamProjectAccessByProject(projectId, teamId); + } + + /** + * Revoke access to a team for a project. This method allows you to revoke the access that a project has to a team, + * which will remove the project's permissions and access to the team. Once the request is accepted, the project will + * no longer have access to the team. + * @param teamId - The ID of the team to revoke access from. + * @param projectId - The ID of the project to revoke access for. This should be a valid identifier for a project that + * is associated with the team. + * @return An AcceptedResponse indicating that the request to revoke access has been accepted. The client should check + * the status of the request to confirm that the access has been revoked. + * @throws An error if the team ID or project ID is invalid, or if there is an issue with the API request. + */ + async revokeTeamProjectAccessByTeam(teamId: string, projectId: string): Promise { + return await this.client.teams.revokeTeamProjectAccessByTeam(teamId, projectId); + } + + /** + * Get the access details of a user to a project. This method retrieves the access information for a specific user in + * relation to a project, including the level of access granted to the user, the permissions they have, and any + * relevant metadata about the user's access to the project. + * @param projectId - The ID of the project to retrieve the user access for. + * @param userId - The ID of the user to retrieve access details for. This should be a valid identifier for a user + * that is associated with the project. + * @returns The access details of the specified user to the project, including the level of access, permissions, and + * any relevant metadata. + * @throws An error if the project ID or user ID is invalid, or if there is an issue with the API request. + */ + async getUserProjectAccessByProject( + projectId: string, + userId: string, + ): Promise { + return await this.client.users.getUserProjectAccessByProject(projectId, userId); + } + + /** + * Grant access to a project for a user. This method allows you to grant a specific level of access to a project for a + * user, along with any relevant permissions. The access details will be defined in the request body, and once the + * request is accepted, the user will have the specified access to the project. + * @param projectId - The ID of the project to grant access to. + * @param access - The access details to grant to users for the project, including the level of access, permissions, + * and any relevant metadata. + * @return An AcceptedResponse indicating that the request to grant access has been accepted. The client should check + * the status of the request to confirm that the access has been granted. + * @throws An error if the project ID is invalid, if the access details are invalid, or if there is an issue with the + * API request. + */ + async grantUserProjectAccessByProject( + projectId: string, + access: GrantProjectUserAccessRequestInner[], + ): Promise { + return await this.client.users.grantUserProjectAccessByProject(projectId, access); + } + + /** + * Revoke access to a project for a user. This method allows you to revoke the access that a user has to a project, + * which will remove the user's permissions and access to the project. Once the request is accepted, the user will no + * longer have access to the project. + * @param projectId - The ID of the project to revoke access from. + * @param userId - The ID of the user to revoke access for. This should be a valid identifier for a user that is + * associated with the project. + * @throws An error if the project ID or user ID is invalid, or if there is an issue with the API request. + */ + async revokeUserProjectAccessByProject(projectId: string, userId: string): Promise { + return await this.client.users.revokeUserProjectAccessByProject(projectId, userId); + } + + /** + * Update the access details of a user to a project. This method allows you to modify the level of access or + * permissions that a user has to a project. + * @param projectId - The ID of the project to update user access for. + * @param userId - The ID of the user to update access for. This should be a valid identifier for a user that is + * associated with the project. + * @param access - The new access details to apply to the user for the project, including the updated level of access, + * permissions, and any relevant metadata. + * @throws An error if the project ID or user ID is invalid, if the access details are invalid, or if there is an + * issue with the API request. + */ + async updateUserProjectAccessByProject( + projectId: string, + userId: string, + access: GrantProjectUserAccessRequestInner, + ): Promise { + return await this.client.users.updateUserProjectAccessByProject(projectId, userId, access); + } + + /** + * List the access details of all users to a project. This method retrieves a list of all users that have access to a + * project, along with the access details for each user, including the level of access, permissions, and any relevant + * metadata about their access to the project. + * @param projectId - The ID of the project to list user access for. + * @param filters - Optional parameters to filter or paginate the list of user access details. + * @return A list of user access details for all users that have access to the specified project, including the level + * of access, permissions, and any relevant metadata. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listUserProjectAccessByProject( + projectId: string, + filters?: FilterListProjectUserAccess, + ): Promise { + return await this.client.users.listUserProjectAccessByProject(projectId, filters); + } + + /** + * List the access details of all projects to a user. This method retrieves a list of all projects that a user has + * access to, along with the access details for each project, including the level of access, permissions, and any + * relevant metadata about their access to the projects. + * @param userId - The ID of the user to list project access for. + * @param filters - Optional parameters to filter or paginate the list of project access details. + * @return A list of project access details for all projects that the specified user has access to, including the + * level of access, permissions, and any relevant metadata. + * @throws An error if the user ID is invalid, or if there is an issue with the API request. + */ + async listUserProjectAccessByUser( + userId: string, + filters?: FilterListUserProjectAccess, + ): Promise { + return await this.client.users.listUserProjectAccessByUser(userId, filters); + } + + /** + * List all environments associated with a project. This method retrieves a list of all environments that are linked + * to the specified project. + * @param projectId - The ID of the project to list environments for. + * @return A list of environments that are associated with the specified project, including details such as the + * environment name, ID, and other relevant metadata. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listEnvironments(projectId: string): Promise { + return await this.client.environments.list(projectId); + } +} diff --git a/src/core/tasks/repositories.ts b/src/core/tasks/repositories.ts new file mode 100644 index 0000000..1856240 --- /dev/null +++ b/src/core/tasks/repositories.ts @@ -0,0 +1,119 @@ +import { UpsunClient } from '../../upsun.js'; +import { Blob, Commit, Ref, SystemInformation, Tree } from '../../model/index.js'; +import { TaskBase } from './task_base.js'; +import { RepositoryApi, SystemInformationApi } from '../../index.js'; + +export class RepositoriesTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private repositoryApi: RepositoryApi, + private systemInfoApi: SystemInformationApi, + ) { + super(client); + } + + /** + * Get a Git blob by its ID in the specified project. This method retrieves the details of a Git blob, including its + * content, encoding, and any relevant metadata. The blob ID should be a valid identifier for a Git blob within the + * project's repository. + * @param projectId - The ID of the project to retrieve the Git blob from. + * @param repositoryBlobId - The ID of the Git blob to retrieve. This should be a valid identifier for a Git blob + * within the project's repository. + * @return The details of the specified Git blob, including its content, encoding, and any relevant metadata. + * @throws An error if the project ID or repository blob ID is invalid, or if there is an issue with the API request. + */ + async getGitBlob(projectId: string, repositoryBlobId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkRepositoryBlobId(repositoryBlobId); + + return await this.repositoryApi.getProjectsGitBlobs({ projectId, repositoryBlobId }); + } + + /** + * Get a Git commit by its ID in the specified project. This method retrieves the details of a Git commit, including + * its message, author, committer, timestamp, and any relevant metadata. The commit ID should be a valid identifier + * for a Git commit within the project's repository. + * @param projectId - The ID of the project to retrieve the Git commit from. + * @param repositoryCommitId - The ID of the Git commit to retrieve. This should be a valid identifier for a Git + * commit within the project's repository. + * @return The details of the specified Git commit, including its message, author, committer, timestamp, and any + * relevant metadata. + * @throws An error if the project ID or repository commit ID is invalid, or if there is an issue with the API + * request. + */ + async getGitCommit(projectId: string, repositoryCommitId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkRepositoryCommitId(repositoryCommitId); + + return await this.repositoryApi.getProjectsGitCommits({ projectId, repositoryCommitId }); + } + + /** + * Get a Git reference (e.g., branch or tag) by its ID in the specified project. + * @param projectId + * @param repositoryRefId Id of the Git reference to retrieve + * (e.g., "heads/main" for the main branch or "tags/v1.0" for a tag). + * @returns + */ + async getGitRef(projectId: string, repositoryRefId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkRepositoryRefId(repositoryRefId); + + return await this.repositoryApi.getProjectsGitRefs({ projectId, repositoryRefId }); + } + + /** + * List all Git references (e.g., branches and tags) in the specified project. This method retrieves a list of all Git + * references that exist within the project's repository, including details such as the reference name, type + * (branch or tag), and the commit it points to. The returned list includes the details of each Git reference that + * belongs to the project. + * @param projectId - The ID of the project to list Git references for. + * @return A list of Git references (branches and tags) that exist within the specified project's repository, + * including details such as the reference name, type, and the commit it points to. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async listGitRefs(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.repositoryApi.listProjectsGitRefs({ projectId }); + } + + /** + * Get a Git tree by its ID in the specified project. This method retrieves the details of a Git tree, including its + * entries (files and subdirectories), their types, and any relevant metadata. The tree ID should be a valid + * identifier for a Git tree within the project's repository. + * @param projectId - The ID of the project to retrieve the Git tree from. + * @param repositoryTreeId - The ID of the Git tree to retrieve. This should be a valid identifier for a Git tree + * within the project's repository. + * @return The details of the specified Git tree, including its entries (files and subdirectories), their types, and any + * relevant metadata. + * @throws An error if the project ID or repository tree ID is invalid, or if there is an issue with the API request. + */ + async getGitTree(projectId: string, repositoryTreeId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkRepositoryTreeId(repositoryTreeId); + + return await this.repositoryApi.getProjectsGitTrees({ projectId, repositoryTreeId }); + } + + //TODO internal? seems that it's not public endpoint + // async restartGitServer(projectId: string): Promise { + // TaskBase.checkProjectId(projectId); + + // return await this.systemInfoApi.actionProjectsSystemRestart({ projectId }); + // } + + /** + * Get GIT related system information for a project. This method retrieves details about the Git system associated + * with the specified project. + * @param projectId - The ID of the project to retrieve Git system information for. + * @return The Git system information for the specified project, including details such as the Git server status, + * repository information, and any relevant metadata about the Git system that is associated with the project. + * @throws An error if the project ID is invalid, or if there is an issue with the API request. + */ + async getGitInfo(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.systemInfoApi.getProjectsSystem({ projectId }); + } +} diff --git a/src/core/tasks/resources.ts b/src/core/tasks/resources.ts index 05210ca..4fd0bcf 100644 --- a/src/core/tasks/resources.ts +++ b/src/core/tasks/resources.ts @@ -1,22 +1,147 @@ -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; -//import { ResourceApi } from "../hack/ResourceApi.js"; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; +import { AutoscalingApi, DeploymentApi } from '../../api/index.js'; +import { + AcceptedResponse, + AutoscalerSettings, + Resources, + UpdateProjectsEnvironmentsDeploymentsNextRequestServicesValue, + UpdateProjectsEnvironmentsDeploymentsNextRequestWebappsValue, + UpdateProjectsEnvironmentsDeploymentsNextRequestWorkersValue, +} from '../../index.js'; +import { DeploymentResourceGroup } from '../model.js'; export class ResourcesTask extends TaskBase { - private resApi: any; // = new ResourceApi(this.client.apiConfig); - - constructor(protected readonly client: UpsunClient) { + constructor( + protected readonly client: UpsunClient, + private deploymentApi: DeploymentApi, + private autoscalingApi: AutoscalingApi, + ) { super(client); } - async get(projectId: string, environmentId: string) { - throw new Error("Not implemented"); + /** + * Get the resource configuration for a specific application in the current deployment of an environment. + * This method retrieves the resource configuration for a specific application (webapp, service, or worker) in the + * current deployment of an environment. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to get the resource configuration for. + * @param type - The type of application to get the resource configuration for. This should be one of 'webapps', + * 'services', or 'workers' depending on the type of application you want to retrieve the resources for. + * @param app - The name of the application to get the resource configuration for. This should be the name of a + * specific application within the specified type. + * @return The resource configuration for the specified application in the current deployment of the environment. This + * includes details such as the profile size, disk space, and instance count for the application. If the application + * is not found, an empty object is returned. + * @throws An error if the project ID, environment ID, type, or app name is invalid, or if there is an issue with the + * API request. + */ + async get( + projectId: string, + environmentId: string, + type: DeploymentResourceGroup = DeploymentResourceGroup.webapps, + app: string = 'app', + ): Promise { + const currentDeployment = await this.client.environments.getDeployment( + projectId, + environmentId, + 'current', + ); - // return await this.resApi.getNextDeployement({ projectId, environmentId }); + if (!currentDeployment) { + return {} as Resources; + } + const group = currentDeployment[type] ?? {}; + + return group[app]?.resources ?? ({} as Resources); } - async set(organizationId: string) { - throw new Error("Not implemented"); + /** + * Update the next deployment’s resource config. + * + * @param projectId Upsun project ID. + * @param environmentId Environment slug (e.g., `main`). + * @param webapps map of ` => { resources?: { profileSize?: string }, disk?: number, instanceCount?: number }` + * @param services map of ` => { resources?: { profileSize?: string }, disk?: number }` + * @param workers map of ` => { resources?: { profileSize?: string }, instanceCount?: number }` + * + * Only include the entries you actually want to change; the API merges the provided settings into the next deployment draft. + */ + async set( + projectId: string, + environmentId: string, + webapps: { + [key: string]: UpdateProjectsEnvironmentsDeploymentsNextRequestWebappsValue; + } = {} as { [key: string]: UpdateProjectsEnvironmentsDeploymentsNextRequestWebappsValue }, + services: { + [key: string]: UpdateProjectsEnvironmentsDeploymentsNextRequestServicesValue; + } = {} as { [key: string]: UpdateProjectsEnvironmentsDeploymentsNextRequestServicesValue }, + workers: { + [key: string]: UpdateProjectsEnvironmentsDeploymentsNextRequestWorkersValue; + } = {} as { [key: string]: UpdateProjectsEnvironmentsDeploymentsNextRequestWorkersValue }, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.deploymentApi.updateProjectsEnvironmentsDeploymentsNext({ + projectId, + environmentId, + updateProjectsEnvironmentsDeploymentsNextRequest: { + webapps, + services, + workers, + }, + }); } + /** + * Get the autoscaler settings for the environment. Autoscaling allows the environment to automatically scale its + * resources up or down based on the current load and traffic. The autoscaler settings include information about + * whether autoscaling is enabled, the addresses that are being autoscaled, and any authentication settings for the + * autoscaler services. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to get the autoscaler settings for. + * @return The autoscaler settings for the specified environment. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async getAutoscalerSettings( + projectId: string, + environmentId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.autoscalingApi.getAutoscalerSettings({ + projectId, + environmentId, + }); + } + + /** + * Update the autoscaler settings for the environment. Autoscaling allows the environment to automatically scale its + * resources up or down based on the current load and traffic. The autoscaler settings include information about + * whether autoscaling is enabled, the addresses that are being autoscaled, and any authentication settings for the + * autoscaler services. Updating the autoscaler settings will allow you to enable or disable autoscaling, change the + * addresses that are being autoscaled, and update the authentication settings for the autoscaler services. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment to update the autoscaler settings for. + * @param params - The new autoscaler settings for the environment. + * @return The updated autoscaler settings for the environment. + * @throws An error if the project ID or environment ID is invalid, if the parameters are invalid, or if there is an + * issue with the API request. + */ + async updateAutoscalerSettings( + projectId: string, + environmentId: string, + params: AutoscalerSettings, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.autoscalingApi.postAutoscalerSettings({ + projectId, + environmentId, + autoscalerSettings: params, + }); + } } diff --git a/src/core/tasks/route.ts b/src/core/tasks/route.ts deleted file mode 100644 index 92aa988..0000000 --- a/src/core/tasks/route.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { RoutingApi } from "../../apis-gen/index.js"; -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class RouteTask extends TaskBase { - private rteApi: RoutingApi; - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.rteApi = new RoutingApi(this.client.apiConfig); - } - - async get(projectId: string, env_name: string, routeId: string) { - return await this.rteApi.getProjectsEnvironmentsRoutes({ projectId, environmentId: env_name, routeId }); - } - - async list(projectId: string, env_name: string) { - return await this.rteApi.listProjectsEnvironmentsRoutes({ projectId, environmentId: env_name }); - } - - // async web(projectId: string) { - // const api = new ProjectDiscoveryApi(this.client.apiConfig); - // return await api.locateProject({ projectId }); - // } -} diff --git a/src/core/tasks/routes.ts b/src/core/tasks/routes.ts new file mode 100644 index 0000000..4da04a4 --- /dev/null +++ b/src/core/tasks/routes.ts @@ -0,0 +1,64 @@ +import { RoutingApi } from '../../api/index.js'; +import { Route, RouteCollection } from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; + +export class RoutesTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private rteApi: RoutingApi, + ) { + super(client); + } + + /** + * Get the details of a specific route for an environment. This method retrieves the details of a specific route that + * is associated with the specified environment. + * @param projectId - The ID of the project to get the route details for. + * @param environmentId - The ID of the environment to get the route details for. + * @param routeId - The ID of the route to retrieve details for. This should be a valid identifier for a route that is + * associated with the specified environment. + * @return The details of the specified route, including information such as the route pattern, target service, and + * other relevant details. + * @throws An error if the project ID, environment ID, or route ID is invalid, or if there is an issue with the API + * request. + */ + async get(projectId: string, environmentId: string, routeId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + RoutesTask.checkRouteId(routeId); + + return await this.rteApi.getProjectsEnvironmentsRoutes({ + projectId, + environmentId, + routeId, + }); + } + + /** + * List all routes for an environment. This method retrieves a list of all routes that are associated with the + * specified environment. + * @param projectId - The ID of the project to list routes for. + * @param environmentId - The ID of the environment to list routes for. + * @return A list of routes that are associated with the specified environment, including details such as the route + * pattern, target service, and other relevant details for each route. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async list(projectId: string, environmentId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.rteApi.listProjectsEnvironmentsRoutes({ projectId, environmentId }); + } + + /** + * Static method to validate a route ID. This method checks if the provided route ID is valid and throws an error if + * it is not. + * @param routeId + */ + static checkRouteId(routeId: string): void { + if (!routeId) { + throw new Error('Route ID is required'); + } + } +} diff --git a/src/core/tasks/service.ts b/src/core/tasks/service.ts deleted file mode 100644 index baa5401..0000000 --- a/src/core/tasks/service.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class ServiceTask extends TaskBase { - - constructor(protected readonly client: UpsunClient) { - super(client); - } - -} diff --git a/src/core/tasks/services.ts b/src/core/tasks/services.ts new file mode 100644 index 0000000..7e7472f --- /dev/null +++ b/src/core/tasks/services.ts @@ -0,0 +1,30 @@ +import { ServicesValue } from '../../model/ServicesValue.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; + +export class ServicesTask extends TaskBase { + constructor(protected readonly client: UpsunClient) { + super(client); + } + + /** + * List services for an environment. This method retrieves the current deployment for the environment and returns the + * `services` property from the deployment details, which contains the configuration of all services for the + * environment. The returned object is a mapping of service names to their respective configuration details. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment. + * @return A mapping of service names to their respective configuration details for the specified environment. + * If there are no services found in the current deployment, an empty object is returned. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue retrieving the deployment + * details. + */ + async list(projectId: string, environmentId: string): Promise<{ [key: string]: ServicesValue }> { + const currentDeployment = await this.client.environments.getDeployment( + projectId, + environmentId, + 'current', + ); + + return currentDeployment.services || {}; + } +} diff --git a/src/core/tasks/source-operation.ts b/src/core/tasks/source-operation.ts deleted file mode 100644 index 0f04926..0000000 --- a/src/core/tasks/source-operation.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class SourceOperationTask extends TaskBase { - - constructor(protected readonly client: UpsunClient) { - super(client); - } - -} diff --git a/src/core/tasks/source-operations.ts b/src/core/tasks/source-operations.ts new file mode 100644 index 0000000..0e5b7cf --- /dev/null +++ b/src/core/tasks/source-operations.ts @@ -0,0 +1,66 @@ +import { SourceOperationsApi } from '../../api/SourceOperationsApi.js'; +import { AcceptedResponse } from '../../model/AcceptedResponse.js'; +import { EnvironmentSourceOperationCollection } from '../../model/EnvironmentSourceOperationCollection.js'; +import { EnvironmentSourceOperationInput } from '../../model/EnvironmentSourceOperationInput.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; + +export class SourceOperationsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private sourceOperationsApi: SourceOperationsApi, + ) { + super(client); + } + + /** + * List source operations for an environment. This method retrieves a list of all source operations that are + * associated with the specified project and environment. + * @param projectId - The ID of the project to list source operations for. + * @param environmentId - The ID of the environment to list source operations for. + * @return A list of source operations that are associated with the specified project and environment, including + * details such as the operation type, status, and other relevant details for each source operation. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request. + */ + async list( + projectId: string, + environmentId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.sourceOperationsApi.listProjectsEnvironmentsSourceOperations({ + projectId, + environmentId, + }); + } + + /** + * Run a source operation for an environment. This method allows you to run a source operation for a specified project + * and environment by providing the necessary parameters for the operation. + * @param projectId - The ID of the project to run the source operation for. + * @param environmentId - The ID of the environment to run the source operation for. + * @param params - An object containing the necessary parameters for the source operation. The specific parameters + * required will depend on the type of source operation being run, and may include details such as the operation type, + * source details, and other relevant information. + * @return An AcceptedResponse indicating that the source operation request has been accepted. The client should check + * the status of the source operation through the operation details to confirm whether it was executed successfully or + * if there were any issues. + * @throws An error if the project ID or environment ID is invalid, if the required parameters for the source + * operation are missing or incorrect, or if there is an issue with the API request. + */ + async run( + projectId: string, + environmentId: string, + params: EnvironmentSourceOperationInput, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.sourceOperationsApi.runSourceOperation({ + projectId, + environmentId, + environmentSourceOperationInput: params, + }); + } +} diff --git a/src/core/tasks/ssh.ts b/src/core/tasks/ssh.ts index c2f6b24..9187c2c 100644 --- a/src/core/tasks/ssh.ts +++ b/src/core/tasks/ssh.ts @@ -1,23 +1,72 @@ -import { SSHKeysApi } from "../../apis-gen/index.js"; -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; +import { SshKeysApi } from '../../api/index.js'; +import { SshKey } from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; export class SshTask extends TaskBase { - - list(userId: string) { - throw new Error('Method not implemented.'); - } - delete(userId: string, arg1: string) { - throw new Error('Method not implemented.'); + constructor( + protected readonly client: UpsunClient, + private sshKeysApi = new SshKeysApi(client.apiConfig), + ) { + super(client); } - constructor(protected readonly client: UpsunClient) { - super(client); + /** + * Add a new SSH key for the user. This method allows you to add a new SSH key for the user by providing the key + * value, and optionally a user ID and title for the key. The method returns the details of the newly added SSH key, + * including the key ID, value, title, and other relevant information. + * @param value - The value of the SSH key to add. This should be the public key string that you want to associate + * with the user. + * @param userId - (Optional) The ID of the user to associate the SSH key with. If not provided, the key will be + * associated with the currently authenticated user. + * @param title - (Optional) A title or description for the SSH key. This can be used to help identify the key later + * on. + * @return The details of the newly added SSH key, including the key ID, value, title, and other relevant information. + * @throws An error if the SSH key value is not provided, if the user ID is invalid, or if there is an issue with the + * API request to add the SSH key. + */ + async add(value: string, userId: string, title?: string): Promise { + TaskBase.checkUserId(userId); + + if (!value) { + throw new Error('SSH key value is required'); + } + + return await this.sshKeysApi.createSshKey({ + createSshKeyRequest: { uuid: userId, value, title }, + }); } - async add(user_id: string, ssh_key: string, key_id: string) { - const api = new SSHKeysApi(this.client.apiConfig); - return await api.createSshKey({createSshKeyRequest: { uuid: user_id, value: ssh_key, title:key_id }}); + /** + * Get the details of an SSH key by its ID. This method allows you to retrieve the details of a specific SSH key by + * providing the key ID. The method returns the details of the SSH key, including the key ID, value, title, and other + * relevant information. + * @param keyId - The ID of the SSH key to retrieve the details for. This should be a positive integer that uniquely + * identifies the SSH key within the system. + * @return The details of the SSH key with the specified ID, including the key ID, value, title, and other relevant + * information. If the SSH key with the specified ID is not found, an error will be thrown. + * @throws An error if the key ID is invalid (e.g., not a positive integer) or if there is an issue with the API + * request to retrieve the SSH key details. + */ + async get(keyId: number): Promise { + TaskBase.checkSshKeyId(keyId); + + return await this.sshKeysApi.getSshKey({ keyId }); } + /** + * Delete an SSH key by its ID. This method allows you to delete a specific SSH key by providing the key ID. The + * method returns nothing if the deletion is successful. + * @param keyId - The ID of the SSH key to delete. This should be a positive integer that uniquely identifies the SSH + * key within the system. + * @return Nothing if the deletion is successful. If the SSH key with the specified ID is not found, an error will be + * thrown. + * @throws An error if the key ID is invalid (e.g., not a positive integer) or if there is an issue with the API + * request to delete the SSH key. + */ + async delete(keyId: number): Promise { + TaskBase.checkSshKeyId(keyId); + + return await this.sshKeysApi.deleteSshKey({ keyId }); + } } diff --git a/src/core/tasks/taskBase.ts b/src/core/tasks/taskBase.ts deleted file mode 100644 index e3e45b9..0000000 --- a/src/core/tasks/taskBase.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; - - -export abstract class TaskBase { - - constructor(protected readonly client: UpsunClient) { } - - static checkProjectId(projectId: string) { - if (!projectId) { - throw new Error("Project ID is required"); - } - } - - static checkOrganizationId(organizationId: string) { - if (!organizationId) { - throw new Error("Organization ID is required"); - } - } - - static checkEnvironmentId(environmentId: string) { - if (!environmentId) { - throw new Error("Environment ID is required"); - } - } - - static checkActivityId(activityId: string) { - if (!activityId) { - throw new Error("Activity ID is required"); - } - } - - static checkApplicationId(applicationId: string) { - if (!applicationId) { - throw new Error("Application ID is required"); - } - } - - static checkBackupId(backupId: string) { - if (!backupId) { - throw new Error("Backup ID is required"); - } - } - - static checkCertificateId(certificateId: string) { - if (!certificateId) { - throw new Error("Certificate ID is required"); - } - } -} diff --git a/src/core/tasks/task_base.ts b/src/core/tasks/task_base.ts new file mode 100644 index 0000000..5044e16 --- /dev/null +++ b/src/core/tasks/task_base.ts @@ -0,0 +1,180 @@ +import { UpsunClient } from '../../upsun.js'; + +export abstract class TaskBase { + constructor(protected readonly client: UpsunClient) {} + + static checkUserId(userId: string): void { + if (!userId) { + throw new Error('User ID is required'); + } + } + + static checkProjectId(projectId: string): void { + if (!projectId) { + throw new Error('Project ID is required'); + } + } + + static checkOrganizationId(organizationId: string): void { + if (!organizationId) { + throw new Error('Organization ID is required'); + } + } + + static checkEnvironmentId(environmentId: string): void { + if (!environmentId) { + throw new Error('Environment ID is required'); + } + } + + static checkActivityId(activityId: string): void { + if (!activityId) { + throw new Error('Activity ID is required'); + } + } + + static checkApplicationId(applicationId: string): void { + if (!applicationId) { + throw new Error('Application ID is required'); + } + } + + static checkBackupId(backupId: string): void { + if (!backupId) { + throw new Error('Backup ID is required'); + } + } + + static checkCertificateId(certificateId: string): void { + if (!certificateId) { + throw new Error('Certificate ID is required'); + } + } + + static checkSubscriptionId(subscriptionId: string): void { + if (!subscriptionId) { + throw new Error('Subscription ID is required'); + } + } + + static checkTeamId(teamId: string): void { + if (!teamId) { + throw new Error('Team ID is required'); + } + } + + static checkDeploymentId(deploymentId: string): void { + if (!deploymentId) { + throw new Error('Deployment ID is required'); + } + } + + static checkInvoiceId(invoiceId: string): void { + if (!invoiceId) { + throw new Error('Invoice ID is required'); + } + } + + static checkOrderId(orderId: string): void { + if (!orderId) { + throw new Error('Order ID is required'); + } + } + + static checkVoucherCode(code: string): void { + if (!code) { + throw new Error('Voucher code is required'); + } + } + + static checkProjectRegion(region: string): void { + if (!region) { + throw new Error('Project region is required'); + } + } + + static checkVariableId(variableId: string): void { + if (!variableId) { + throw new Error('Variable ID is required'); + } + } + + static checkRepositoryBlobId(repositoryBlobId: string): void { + if (!repositoryBlobId) { + throw new Error('Repository Blob ID is required'); + } + } + + static checkRepositoryCommitId(repositoryCommitId: string): void { + if (!repositoryCommitId) { + throw new Error('Repository Commit ID is required'); + } + } + + static checkRepositoryRefId(repositoryRefId: string): void { + if (!repositoryRefId) { + throw new Error('Repository Ref ID is required'); + } + } + + static checkRepositoryTreeId(repositoryTreeId: string): void { + if (!repositoryTreeId) { + throw new Error('Repository Tree ID is required'); + } + } + + static checkIntegrationId(integrationId: string): void { + if (!integrationId) { + throw new Error('Integration ID is required'); + } + } + + static checkDomainId(domainId: string): void { + if (!domainId) { + throw new Error('Domain ID is required'); + } + } + + static checkApiTokenId(tokenId: string): void { + if (!tokenId) { + throw new Error('API Token ID is required'); + } + } + + static checkEmail(email: string): void { + if (!email) { + throw new Error('Email is required'); + } + + if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { + throw new Error('Invalid email format'); + } + } + + static checkInviteId(inviteId: string): void { + if (!inviteId) { + throw new Error('Invite ID is required'); + } + } + + static checkUsername(username: string): void { + if (!username) { + throw new Error('Username is required'); + } + } + + static checkSshKeyId(keyId: number): void { + if (!keyId || keyId <= 0) { + throw new Error('Key ID must be a positive integer'); + } + } + + // works for URIs like /subscriptions/{subscriptionId} to extract subscriptionId + // as the subscriptionId is not returned directly in the project object (emty field) + // e.g. /subscriptions/abc123 + static extractSubscriptionId(projectLicenceUri: string): string { + const url = new URL(projectLicenceUri); + const path = url.pathname; + return path.substring(path.lastIndexOf('/') + 1); + } +} diff --git a/src/core/tasks/team.ts b/src/core/tasks/team.ts deleted file mode 100644 index 12a0927..0000000 --- a/src/core/tasks/team.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class TeamTask extends TaskBase { - - constructor(protected readonly client: UpsunClient) { - super(client); - } - -} diff --git a/src/core/tasks/teams.ts b/src/core/tasks/teams.ts new file mode 100644 index 0000000..c8403e0 --- /dev/null +++ b/src/core/tasks/teams.ts @@ -0,0 +1,402 @@ +import { ListTeamsRequest, TeamsApi } from '../../api/TeamsApi.js'; +import { + GrantProjectTeamAccessRequestInner, + GrantTeamProjectAccessRequestInner, + ListProjectTeamAccess200Response, + ListTeamMembers200Response, + ListTeams200Response, + Team, + TeamAccessApi, + TeamMember, + TeamProjectAccess, + UpdateTeamRequest, +} from '../../index.js'; +import { UpsunClient } from '../../upsun.js'; +import { + FilterListProjectTeamAccess, + FilterListTeamMembers, + FilterListTeamProjectAccess, + FilterListUserTeams, +} from '../model.js'; +import { TaskBase } from './task_base.js'; + +export class TeamsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private teamsApi: TeamsApi, + private teamAccessApi: TeamAccessApi, + ) { + super(client); + } + + /** + * Create a new team within an organization. This method allows you to create a new team by providing the organization + * ID, team name (label), and optionally a list of project permissions for the team. The team will be created within + * the specified organization and can be used to manage access to projects and resources within that organization. + * @param organizationId - The ID of the organization to create the team in. This should be a valid organization ID + * that the current user has permission to manage. + * @param label - The name of the team to create. This should be a non-empty string that uniquely identifies the team + * within the specified organization. + * @param projectPermissions - (Optional) An array of project IDs that the team should have access to. This can be + * used to specify the projects that the team will have permissions for. + * @return Nothing if the team is created successfully. If there is an issue with the provided parameters or if the + * API request to create the team fails, an error will be thrown. + * @throws An error if the organization ID is invalid, if the team name is not provided, or if there is an issue with + * the API request to create the team. + */ + async create( + organizationId: string, + label: string, + projectPermissions?: string[], + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + if (!label) { + throw new Error('Team name is required'); + } + + await this.teamsApi.createTeam({ + createTeamRequest: { + organizationId: organizationId, + label: label, + projectPermissions: projectPermissions, + }, + }); + } + + /** + * Delete a team by its ID. This method allows you to delete a specific team by providing the team ID. + * @param teamId - The ID of the team to delete. This should be a valid team ID that exists within the system. + * @throws An error if the team ID is invalid or if there is an issue with the API request to delete the team. + */ + async delete(teamId: string): Promise { + TaskBase.checkTeamId(teamId); + + await this.teamsApi.deleteTeam({ teamId }); + } + + /** + * Get a team by its ID. This method allows you to retrieve the details of a specific team by providing the team ID. + * @param teamId - The ID of the team to retrieve. This should be a valid team ID that exists within the system. + * @returns The team details if found. + * @throws An error if the team ID is invalid or if there is an issue with the API request to get the team. + */ + async get(teamId: string): Promise { + TaskBase.checkTeamId(teamId); + + return await this.teamsApi.getTeam({ teamId }); + } + + /** + * Update a team by its ID. This method allows you to update the details of a specific team by providing the team ID + * and the parameters to update. + * @param teamId - The ID of the team to update. This should be a valid team ID that exists within the system. + * @param params - The parameters to update for the team. This can include the team name (label) and/or the list of + * project permissions for the team. At least one of these parameters must be provided to perform an update. + * @throws An error if the team ID is invalid, if neither label nor projectPermissions is provided, or if there is an + * issue with the API request to update the team. + */ + async update(teamId: string, params?: UpdateTeamRequest): Promise { + TaskBase.checkTeamId(teamId); + + if (!params?.label && !params?.projectPermissions) { + throw new Error('At least one of label or projectPermissions is required to update the team'); + } + + await this.teamsApi.updateTeam({ + teamId: teamId, + updateTeamRequest: params, + }); + } + + /** + * List teams with optional filtering. This method allows you to retrieve a list of teams based on various filter + * criteria. + * @param filters - The filter criteria to apply when listing teams. + * @return A list of teams that match the specified filter criteria. If no teams are found, an empty array is + * returned. + * @throws An error if there is an issue with the API request to list the teams. + */ + async list(filters: ListTeamsRequest): Promise { + return await this.teamsApi.listTeams(filters); + } + + /** + * List all teams that a user is a member of, with optional filtering. This will return a list of teams that the + * specified user is a member of, based on the provided filter criteria. + * @param userId - The ID of the user to list teams for. This should be a valid user ID that exists within the system. + * @param filters - The filter criteria to apply when listing the user's teams. + * @return A list of teams that the specified user is a member of and that match the provided filter criteria. + * If the user is not a member of any teams or if no teams match the filter criteria, an empty array is returned. + * @throws An error if the user ID is invalid or if there is an issue with the API request to list the user's teams. + */ + async listByMember(userId: string, filters?: FilterListUserTeams): Promise { + TaskBase.checkUserId(userId); + + return await this.teamsApi.listUserTeams({ userId, ...filters }); + } + + /** + * Add a member to a team. This method allows you to add a user as a member of a specific team by providing the team + * ID and the user ID. + * @param teamId - The ID of the team to add the member to. This should be a valid team ID that exists within the + * system. + * @param userId - The ID of the user to add as a member. This should be a valid user ID that exists within the + * system. + * @return The details of the newly added team member, including the team ID, user ID, and other relevant information. + * If the team or user ID is invalid, or if there is an issue with the API request to add the member, an error will be + * thrown. + * @throws An error if the team ID or user ID is invalid, or if there is an issue with the API request to add the + * member. + */ + async addMember(teamId: string, userId: string): Promise { + TaskBase.checkTeamId(teamId); + TaskBase.checkUserId(userId); + + return await this.teamsApi.createTeamMember({ + teamId: teamId, + createTeamMemberRequest: { + userId: userId, + }, + }); + } + + /** + * Delete a member from a team. This method allows you to remove a user from being a member of a specific team by + * providing the team ID and the user ID. + * @param teamId - The ID of the team to remove the member from. This should be a valid team ID that exists within the + * system. + * @param userId - The ID of the user to remove as a member. This should be a valid user ID that exists within the + * system. + * @throws An error if the team ID or user ID is invalid, or if there is an issue with the API request to delete the + * member. If the specified user is not a member of the specified team, an error will also be thrown. + */ + async deleteMember(teamId: string, userId: string): Promise { + TaskBase.checkTeamId(teamId); + TaskBase.checkUserId(userId); + + await this.teamsApi.deleteTeamMember({ + teamId: teamId, + userId: userId, + }); + } + + /** + * Get a team member by team ID and user ID. This method allows you to retrieve the details of a specific team member + * by providing the team ID and the user ID. The method returns the details of the team member. + * @param teamId - The ID of the team to retrieve the member from. This should be a valid team ID that exists within + * the system. + * @param userId - The ID of the user to retrieve as a member. This should be a valid user ID that exists within the + * system. + * @return The details of the team member, including the team ID, user ID, and other relevant information. + * @throws An error if the team ID or user ID is invalid, or if there is an issue with the API request to get the team + * member. If the specified user is not a member of the specified team, an error will also be thrown. + */ + async getMember(teamId: string, userId: string): Promise { + TaskBase.checkTeamId(teamId); + TaskBase.checkUserId(userId); + + return await this.teamsApi.getTeamMember({ + teamId: teamId, + userId: userId, + }); + } + + /** + * List members of a team with optional filtering. This method allows you to retrieve a list of members for a specific + * team by providing the team ID and optional filter criteria. + * @param teamId - The ID of the team to list members for. This should be a valid team ID that exists within the + * system. + * @param filters - The filter criteria to apply when listing team members. + * @return A list of team members that match the specified filter criteria for the given team ID. If no members are + * found, an empty list will be returned. + * @throws An error if the team ID is invalid or if there is an issue with the API request to list the team members. + * If the specified team does not exist, an error will also be thrown. + */ + async listMembers( + teamId: string, + filters: FilterListTeamMembers, + ): Promise { + TaskBase.checkTeamId(teamId); + + return await this.teamsApi.listTeamMembers({ teamId, ...filters }); + } + + /** + * Get the project access details for a team to a project ID. + * @param projectId - The ID of the project to get the team access details for. This should be a valid project ID that + * exists within the system. + * @param teamId - The ID of the team to get the access details for. This should be a valid team ID that exists within + * the system. + * @return The team project access details, including the team ID, project ID, and access level. If the specified team + * does not have access to the specified project, an error will be thrown. + * @throws An error if the project ID or team ID is invalid, or if there is an issue with the API request to get the + * team project access details. If the specified team does not have access to the specified project, an error will + * also be thrown. + */ + async getTeamProjectAccessByProject( + projectId: string, + teamId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkTeamId(teamId); + + return await this.teamAccessApi.getProjectTeamAccess({ + teamId: teamId, + projectId: projectId, + }); + } + + /** + * Get the project access details for a team to a project ID. + * @param teamId - The ID of the team to get the access details for. This should be a valid team ID that exists within + * the system. + * @param projectId - The ID of the project to get the team access details for. This should be a valid project ID that + * exists within the system. + * @return The team project access details, including the team ID, project ID, and access level. If the specified team + * does not have access to the specified project, an error will be thrown. + * @throws An error if the team ID or project ID is invalid, or if there is an issue with the API request to get the + * team project access details. If the specified team does not have access to the specified project, an error will + * also be thrown. + */ + async getTeamProjectAccessByTeam(teamId: string, projectId: string): Promise { + TaskBase.checkTeamId(teamId); + TaskBase.checkProjectId(projectId); + + return await this.teamAccessApi.getTeamProjectAccess({ + teamId: teamId, + projectId: projectId, + }); + } + + /** + * Grant a team access to a project. These methods allow you to grant access for a + * team to a project by providing the respective IDs and access details. + * @param projectId - The ID of the project to grant access to. This should be a valid project ID that exists within + * the system. + * @param access - An array of access details specifying the team IDs and access levels to grant for the project. + * Each item in the array should include a team ID and the access level to grant for that team. + * @throws An error if the project ID is invalid, if the access array is empty or contains invalid entries, or if + * there is an issue with the API request to grant access. + */ + async grantTeamProjectAccessToProject( + projectId: string, + access: GrantProjectTeamAccessRequestInner[], + ): Promise { + TaskBase.checkProjectId(projectId); + + if (!access || access.length === 0) { + throw new Error('At least one team ID is required to grant access'); + } + + await this.teamAccessApi.grantProjectTeamAccess({ + projectId: projectId, + grantProjectTeamAccessRequestInner: access, + }); + } + + /** + * Grant a team access to a project for a team. These methods allow you to grant access for a + * team to a project by providing the respective IDs and access details. + * @param teamId - The ID of the team to grant access to. This should be a valid team ID that exists within the system. + * @param access - An array of access details specifying the project IDs and access levels to grant for the team. Each + * item in the array should include a project ID and the access level to grant for that project. + * @throws An error if the team ID is invalid, if the access array is empty or contains invalid entries, or if there + * is an issue with the API request to grant access. + */ + async grantTeamProjectAccessToTeam( + teamId: string, + access: GrantTeamProjectAccessRequestInner[], + ): Promise { + TaskBase.checkTeamId(teamId); + + if (!access || access.length === 0) { + throw new Error('At least one project ID is required to grant access'); + } + + await this.teamAccessApi.grantTeamProjectAccess({ + teamId: teamId, + grantTeamProjectAccessRequestInner: access, + }); + } + + /** + * List the team access details for a project or a team. These methods allow you to retrieve a list of team access + * details for a specific project or team by providing the respective IDs and optional filter criteria. + * @param projectId - The ID of the project to list team access details for. This should be a valid project ID that + * exists within the system. + * @param filters - The filter criteria to apply when listing team access details for the project. + * @return A list of team access details for the specified project that match the provided filter criteria. If no team + * access details are found, an empty list will be returned. + * @throws An error if the project ID is invalid or if there is an issue with the API request to list team access + * details. + */ + async listTeamProjectAccessByProject( + projectId: string, + filters: FilterListProjectTeamAccess, + ): Promise { + TaskBase.checkProjectId(projectId); + + return await this.teamAccessApi.listProjectTeamAccess({ projectId, ...filters }); + } + + /** + * List the team access details for a project or a team. These methods allow you to retrieve a list of team access + * details for a specific project or team by providing the respective IDs and optional filter criteria. + * @param teamId - The ID of the team to list project access details for. This should be a valid team ID that exists + * within the system. + * @param filters - The filter criteria to apply when listing project access details for the team. + * @return A list of team access details for the specified team that match the provided filter criteria. If no team + * access details are found, an empty list will be returned. + * @throws An error if the team ID is invalid or if there is an issue with the API request to list project access + * details. + */ + async listTeamProjectAccessByTeam( + teamId: string, + filters: FilterListTeamProjectAccess, + ): Promise { + TaskBase.checkTeamId(teamId); + + return await this.teamAccessApi.listTeamProjectAccess({ teamId, ...filters }); + } + + /** + * Revoke a team's access to a project. These methods allow you to revoke access for a team to a project by providing + * the respective IDs. + * @param projectId - The ID of the project to revoke access from. This should be a valid project ID that exists + * within the system. + * @param teamId - The ID of the team to revoke access for. This should be a valid team ID that exists within the + * system. + * @throws An error if the project ID or team ID is invalid, or if there is an issue with the API request to revoke + * access. + */ + async revokeTeamProjectAccessByProject(projectId: string, teamId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkTeamId(teamId); + + await this.teamAccessApi.removeProjectTeamAccess({ + projectId: projectId, + teamId: teamId, + }); + } + + /** + * Revoke a team's access to a project. These methods allow you to revoke access for a team to a project by providing + * the respective IDs. + * @param teamId - The ID of the team to revoke access for. This should be a valid team ID that exists within the + * system. + * @param projectId - The ID of the project to revoke access from. This should be a valid project ID that exists + * within the system. + * @throws An error if the team ID or project ID is invalid, or if there is an issue with the API request to revoke + * access. + */ + async revokeTeamProjectAccessByTeam(teamId: string, projectId: string): Promise { + TaskBase.checkTeamId(teamId); + TaskBase.checkProjectId(projectId); + + await this.teamAccessApi.removeTeamProjectAccess({ + teamId: teamId, + projectId: projectId, + }); + } +} diff --git a/src/core/tasks/user.ts b/src/core/tasks/user.ts deleted file mode 100644 index 8b8305f..0000000 --- a/src/core/tasks/user.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { UsersApi } from "../../apis-gen/index.js"; -import { User as UserModel } from "../../apis-gen/models/index.js"; -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class UserTask extends TaskBase { - private usrApi: UsersApi; - - constructor(protected readonly client: UpsunClient) { - super(client); - - this.usrApi = new UsersApi(this.client.apiConfig); - } - - async me(): Promise { - return await this.usrApi.getCurrentUser(); - } -} diff --git a/src/core/tasks/users-invitations.ts b/src/core/tasks/users-invitations.ts new file mode 100644 index 0000000..14a2cef --- /dev/null +++ b/src/core/tasks/users-invitations.ts @@ -0,0 +1,135 @@ +import { OrganizationInvitationsApi, ProjectInvitationsApi } from '../../api/index.js'; +import { + OrganizationInvitation, + OrganizationPermissions, + ProjectInvitation, +} from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { CreateProjectInvite, FilterListOrgInvites, ListProjectInvites } from '../model.js'; +import { TaskBase } from './task_base.js'; + +export class UsersInvitationsTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private orgInvitationsApi: OrganizationInvitationsApi, + private projectInvitationsApi: ProjectInvitationsApi, + ) { + super(client); + } + + /** + * Cancel an organization invitation. + */ + async cancelOrgInvite(organizationId: string, invitationId: string): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkInviteId(invitationId); + + await this.orgInvitationsApi.cancelOrgInvite({ organizationId, invitationId }); + } + + /** + * Create an organization invitation for a specified email address, with the specified permissions. + * @param organizationId - The ID of the organization to create the invitation for. + * @param email - The email address to send the invitation to. + * @param permissions - The permissions to grant to the invitee. This should be an array of permissions that specify + * what actions the invitee will be allowed to perform within the organization (e.g., "read", "write", "admin"). + * @param force - Whether to force the creation of the invitation even if an invitation already exists for the + * specified email address. If true, a new invitation will be created and sent to the email address, replacing any + * existing invitation. If false or not provided, an error will be thrown if an invitation already exists for the + * email address. + * @return The details of the created organization invitation. + * @throws An error if the organization ID is invalid, if the email address is invalid, if permissions are not + * provided, or if there is an issue with the API request. + */ + async createOrgInvite( + organizationId: string, + email: string, + permissions: OrganizationPermissions, + force?: boolean, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + TaskBase.checkEmail(email); + + if (permissions.length === 0) { + throw new Error('Permissions are required'); + } + + return await this.orgInvitationsApi.createOrgInvite({ + organizationId, + createOrgInviteRequest: { email, permissions, force }, + }); + } + + /** + * List all pending invitations for an organization, with optional filtering. + * @param organizationId - The ID of the organization to list invitations for. + * @param filters - Optional filters to apply to the list of invitations, such as filtering by email address or + * permissions. + * @return A list of organization invitations that match the specified filters. + * @throws An error if the organization ID is invalid, if the filters are invalid, or if there is an issue with the + * API request. + */ + async listOrgInvites( + organizationId: string, + filters?: FilterListOrgInvites, + ): Promise { + TaskBase.checkOrganizationId(organizationId); + + return await this.orgInvitationsApi.listOrgInvites({ organizationId, ...filters }); + } + + /** + * Cancel a project invitation. + * @param projectId - The ID of the project to cancel the invitation for. + * @param invitationId - The ID of the invitation to cancel. + * @return A promise that resolves when the invitation has been canceled. + * @throws An error if the project ID or invitation ID is invalid, or if there is an issue with the API request. + */ + async cancelProjectInvite(projectId: string, invitationId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkInviteId(invitationId); + + await this.projectInvitationsApi.cancelProjectInvite({ projectId, invitationId }); + } + + /** + * Create a project invitation for a specified email address, with the specified role and permissions. + * @param projectId - The ID of the project to create the invitation for. + * @param email - The email address to send the invitation to. + * @param params - The parameters for the project invitation, including the role to assign to the invitee and any + * specific permissions to grant within the project. + * @return The details of the created project invitation. + * @throws An error if the project ID is invalid, if the email address is invalid, if the parameters are invalid, or + * if there is an issue with the API request. + */ + async createProjectInvite( + projectId: string, + email: string, + params: CreateProjectInvite, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEmail(email); + + return await this.projectInvitationsApi.createProjectInvite({ + projectId, + createProjectInviteRequest: { email, ...params }, + }); + } + + /** + * List all pending invitations for a project, with optional filtering. + * @param projectId - The ID of the project to list invitations for. + * @param filters - Optional filters to apply to the list of invitations, such as filtering by email address or role. + * @return A list of project invitations that match the specified filters. + * @throws An error if the project ID is invalid, if the filters are invalid, or if there is an issue with the API + * request. + */ + async listProjectInvites( + projectId: string, + filters?: ListProjectInvites, + ): Promise { + TaskBase.checkProjectId(projectId); + + return await this.projectInvitationsApi.listProjectInvites({ projectId, ...filters }); + } +} diff --git a/src/core/tasks/users.ts b/src/core/tasks/users.ts new file mode 100644 index 0000000..7684f7f --- /dev/null +++ b/src/core/tasks/users.ts @@ -0,0 +1,915 @@ +import { + ApiTokensApi, + ConnectionsApi, + GrantsApi, + MfaApi, + PhoneNumberApi, + UserAccessApi, + UserProfilesApi, + UsersApi, +} from '../../api/index.js'; +import { + Address, + ApiToken, + ConfirmTotpEnrollment200Response, + Connection, + GetAddress200Response, + GetCurrentUserVerificationStatus200Response, + GetCurrentUserVerificationStatusFull200Response, + GetTotpEnrollment200Response, + GrantProjectUserAccessRequestInner, + GrantUserProjectAccessRequestInner, + ListProfiles200Response, + ListProjectUserAccess200Response, + ListUserExtendedAccess200Response, + Profile, + UpdateProfileRequest, + UpdateProjectUserAccessRequest, + UpdateUserRequest, + User as UserModel, + UserProjectAccess, + VerifyPhoneNumberRequestChannelEnum, +} from '../../model/index.js'; +import { UpsunClient } from '../../upsun.js'; +import { FilterListProjectUserAccess, FilterListUserExtendedAccess } from '../model.js'; +import { TaskBase } from './task_base.js'; + +export class UsersTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private readonly usersApi: UsersApi, + private readonly userProfilesApi: UserProfilesApi, + private readonly userAccessApi: UserAccessApi, + private readonly apiTokensApi: ApiTokensApi, + private readonly connectionsApi: ConnectionsApi, + private readonly grantsApi: GrantsApi, + private readonly mfaApi: MfaApi, + private readonly phoneNumberApi: PhoneNumberApi, + ) { + super(client); + } + + /** + * Retrieves information about the currently authenticated user. + * @return The details of the currently authenticated user, including their user ID, email address, full name, and + * other relevant information. This method is useful for retrieving information about the user who is currently logged + * in and authenticated with the system, allowing you to access their details and use that information for various + * purposes. + * @throws An error if there is an issue with the API request to retrieve the current user's information, or if the + * user is not authenticated. + */ + async me(): Promise { + return await this.usersApi.getCurrentUser(); + } + + /** + * Note that user creation is not supported through the API, and this method will throw an error if called. + * Use `upsun.invitations.createOrgInvite()` to invite users to your organization instead, + * or `upsun.invitations.createProjectInvite()` to invite users to specific projects. + * Inviting users to your organization or projects will send them an email invitation, + * which will allow them to create their own accounts and join your organization with the appropriate permissions. + */ + async create(): Promise { + throw new Error( + 'User creation is not supported through the API, invite users to your organization or project instead.', + ); + } + + /** + * Adds users to a project with specified permissions. + * This method allows you to grant access to a project for one or more users, specifying their access levels + * and permissions within the project. + * @param projectId - The ID of the project to grant access to. This should be a valid project ID that exists within + * the system. + * @param userPermissions - An array of user permission details specifying the user IDs and access levels to grant for + * the project. Each item in the array should include a user ID and the access level to grant for that user. + * @throws An error if the project ID is invalid, if the user permissions array is empty, or if there is an issue with + * the API request to grant access. + */ + async addToProject( + projectId: string, + userPermissions: GrantProjectUserAccessRequestInner[], + ): Promise { + TaskBase.checkProjectId(projectId); + + if (!userPermissions || userPermissions.length === 0) { + throw new Error('At least one user permission is required to add a user to a project'); + } + + return await this.userAccessApi.grantProjectUserAccess({ + projectId, + grantProjectUserAccessRequestInner: userPermissions, + }); + } + + /** + * Removes a user's access to a project. + * Note that this does not delete the user from the system, but simply revokes their access to the specified project. + * @param userId - The ID of the user to remove from the project. This should be a valid user ID that exists within + * the system. + * @param projectId - The ID of the project to remove the user from. This should be a valid project ID that exists + * within the system. + * @throws An error if the user ID or project ID is invalid, or if there is an issue with the API request to remove + * the user's access. + */ + async removeFromProject(userId: string, projectId: string): Promise { + TaskBase.checkUserId(userId); + TaskBase.checkProjectId(projectId); + + return await this.userAccessApi.removeProjectUserAccess({ projectId, userId }); + } + + /** + * Retrieves information about a specific user by their ID. + * @param userId - The ID of the user to retrieve information for. This should be a valid user ID that exists within + * the system. + * @return The details of the user with the specified ID, including their username, email address, full name, and + * other relevant information. + * @throws An error if the user ID is invalid or if there is an issue with the API request to retrieve the user's + * information. + */ + async get(userId: string): Promise { + TaskBase.checkUserId(userId); + + return await this.usersApi.getUser({ userId }); + } + + /** + * Lists all users who have access to a specific project, along with their access levels and permissions. + * This method is useful for project administrators to manage and review user access to their projects. + * @param projectId - The ID of the project to list user access for. This should be a valid project ID that exists + * within the system. + * @return A list of users who have access to the specified project, along with their access levels and permissions. + * Each entry in the list provides details about a user's access to the project. + * @throws An error if the project ID is invalid or if there is an issue with the API request to list user access for + * the project. + */ + async listProjectUserAccesses(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.userAccessApi.listProjectUserAccess({ projectId }); + } + + /** + * Updates a user's information, such as their username, first name, last name, picture, company, website, or country. + * @param userId - The ID of the user to update. This should be a valid user ID that exists within the system. + * @param params - The parameters to update for the user, which may include their username, first name, last name, + * picture, company, website, or country. + * @return Nothing if the update is successful. If the user with the specified ID is not found, or if there is an + * issue with the API request to update the user's information. + * @throws An error if the user ID is invalid, if the parameters are invalid, or if there is an issue with the API + * request to update the user's information. + */ + async update(userId: string, params: UpdateUserRequest): Promise { + TaskBase.checkUserId(userId); + + await this.usersApi.updateUser({ + userId, + updateUserRequest: params, + }); + } + + /** + * Retrieves the verification status of the currently authenticated user. + * @returns The verification status of the currently authenticated user, which may include information about whether + * the user has completed any required verification steps, such as email verification or multi-factor authentication + * setup, and whether there are any pending verification actions that the user needs to complete. + * @throws An error if there is an issue with the API request to retrieve the user's verification status. + */ + async getCurrentUserVerificationStatus(): Promise { + return await this.usersApi.getCurrentUserVerificationStatus(); + } + + /** + * Retrieves the full verification status of the currently authenticated user, including detailed information about + * the verification process, pending actions, and any relevant metadata. + * @returns The full verification status of the currently authenticated user, which may include detailed information + * about the verification process, pending actions, and any relevant metadata. + * @throws An error if there is an issue with the API request to retrieve the user's full verification status. + */ + async getCurrentUserVerificationStatusFull(): Promise { + return await this.usersApi.getCurrentUserVerificationStatusFull(); + } + + /** + * Retrieves a user's information by their email address. + */ + async getByEmailAddress(email: string): Promise { + TaskBase.checkEmail(email); + + return await this.usersApi.getUserByEmailAddress({ email }); + } + + /** + * Retrieves a user's information by their username. + * @param username - The username of the user to retrieve information for. This should be a valid username that exists + * within the system. + * @return The details of the user with the specified username, including their user ID, email address, full name, and + * other relevant information. + * @throws An error if the username is invalid or if there is an issue with the API request to retrieve the user's + * information. + */ + async getByUsername(username: string): Promise { + TaskBase.checkUsername(username); + + return await this.usersApi.getUserByUsername({ username }); + } + + /** + * Resets a user's email address. This method can be used to update the email address associated with a user's + * account, which may be necessary if the user has changed their email or if there are issues with the current email + * address on file. + * If no new email address is provided, the user's email will be reset to an empty string, effectively removing the + * email address from their account. + * @param userId - The ID of the user to reset the email address for. This should be a valid user ID that exists + * within the system. + * @param email - (Optional) The new email address to associate with the user's account. If not provided, the user's + * email will be reset to an empty string, effectively removing the email address from their account. + * @return Nothing if the email reset is successful. If the user with the specified ID is not found, or if there is an + * issue with the API request to reset the user's email address. + * @throws An error if the user ID is invalid, if the email address is invalid, or if there is an issue with the API + * request to reset the user's email address. + */ + async resetEmailAddress(userId: string, email?: string): Promise { + TaskBase.checkUserId(userId); + + if (email) { + TaskBase.checkEmail(email); + } + + await this.usersApi.resetEmailAddress({ + userId, + resetEmailAddressRequest: { emailAddress: email || '' }, + }); + } + + /** + * Resets a user's password. This method can be used to initiate a password reset process for a user, which typically + * involves sending a password reset email to the user's registered email address with instructions on how to create + * a new password. + * @param userId - The ID of the user to reset the password for. This should be a valid user ID that exists within the + * system. + * @return Nothing if the password reset process is successfully initiated. If the user with the specified ID is not + * found, or if there is an issue with the API request to initiate the password reset process. + * @throws An error if the user ID is invalid or if there is an issue with the API request to initiate the password + * reset process. + */ + async resetPassword(userId: string): Promise { + TaskBase.checkUserId(userId); + + await this.usersApi.resetPassword({ userId }); + } + + /** + * Retrieves a project's access level and permissions for a specific user. This method is useful for checking what + * level of access a user has to a project, which can help with managing permissions and ensuring that users have the + * appropriate access to perform their tasks within the project. + * @param projectId - The ID of the project to check access for. This should be a valid project ID that exists within + * the system. + * @param userId - The ID of the user to check access for. This should be a valid user ID that exists within the + * system. + * @return The access level and permissions that the specified user has for the specified project. This may include + * details about the user's role within the project, specific permissions granted, and any restrictions on their + * access. + * @throws An error if the project ID or user ID is invalid, or if there is an issue with the API request to retrieve + * the user's access information for the project. + */ + async getUserProjectAccessByProject( + projectId: string, + userId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkUserId(userId); + + return await this.userAccessApi.getProjectUserAccess({ + projectId, + userId, + }); + } + + /** + * Retrieves a user's access level and permissions for a specific project. This method is useful for checking what + * level of access a user has to a project, which can help with managing permissions and ensuring that users have the + * appropriate access to perform their tasks within the project. + * @param userId - The ID of the user to check access for. This should be a valid user ID that exists within the + * system. + * @param projectId - The ID of the project to check access for. This should be a valid project ID that exists within + * the system. + * @return The access level and permissions that the specified user has for the specified project. This may include + * details about the user's role within the project, specific permissions granted, and any restrictions on their + * access. + * @throws An error if the user ID or project ID is invalid, or if there is an issue with the API request to retrieve + * the user's access information for the project. + */ + async getUserProjectAccessByUser(userId: string, projectId: string): Promise { + TaskBase.checkUserId(userId); + TaskBase.checkProjectId(projectId); + + return await this.userAccessApi.getUserProjectAccess({ + projectId, + userId, + }); + } + + /** + * Retrieves a list of all projects that a user has access to, along with their access levels and permissions for each + * project. + * @param projectId - The ID of the project to grant access for. + * @param access - An array of access details specifying the user IDs and access levels to grant for the user. Each + * item in the array should include a user ID and the access level to grant for that project. + * @throws An error if the project ID is invalid, if the access level is invalid, or if there is an issue with the API + * request to list the user's project access information. + */ + async grantUserProjectAccessByProject( + projectId: string, + access: GrantProjectUserAccessRequestInner[], + ): Promise { + TaskBase.checkProjectId(projectId); + + if (!access || access.length === 0) { + throw new Error('At least one user ID is required to grant access'); + } + + await this.userAccessApi.grantProjectUserAccess({ + projectId, + grantProjectUserAccessRequestInner: access, + }); + } + + /** + * Grants a user access to a project with specified permissions. This method allows you to add a user to a project and + * define their access levels and permissions within that project. By granting a user access to a project, you enable + * them to collaborate and contribute to the project according to the permissions you have set. + * @param userId - The ID of the user to grant access to. This should be a valid user ID that exists within the + * system. + * @param access - An array of access details specifying the project IDs and access levels to grant for the user. Each + * item in the array should include a project ID and the access level to grant for that project. + * @throws An error if the user ID is invalid, if the access level is invalid, or if there is an issue with the API + * request to grant the user access to the project. + */ + async grantUserProjectAccessByUser( + userId: string, + access: GrantUserProjectAccessRequestInner[], + ): Promise { + TaskBase.checkUserId(userId); + + if (!access || access.length === 0) { + throw new Error('At least one project ID is required to grant access'); + } + + await this.userAccessApi.grantUserProjectAccess({ + userId, + grantUserProjectAccessRequestInner: access, + }); + } + + /** + * Lists all users who have access to a specific project, along with their access levels and permissions. + * @param projectId - The ID of the project to list user access for. + * @param filters - Optional filters to apply to the list of user access, such as filtering by user ID or access + * level. + * @return A list of users who have access to the specified project, along with their access levels and permissions. + * Each entry in the list provides details about a user's access to the project. + * @throws An error if the project ID is invalid or if there is an issue with the API request to list user access for + * the project. + */ + async listUserProjectAccessByProject( + projectId: string, + filters?: FilterListProjectUserAccess, + ): Promise { + TaskBase.checkProjectId(projectId); + + return await this.userAccessApi.listProjectUserAccess({ + projectId, + ...filters, + }); + } + + /** + * Retrieves a list of all projects that a user has access to, along with their access levels and permissions for each + * project. + * @param userId - The ID of the user to list project access for. This should be a valid user ID that exists within + * the system. + * @param filters - Optional filters to apply to the list of project access, such as filtering by project ID or access + * level. + * @return A list of all projects that the specified user has access to, along with their access levels and + * permissions for each project. + * @throws An error if the user ID is invalid or if there is an issue with the API request to list the user's project + * access information. + */ + async listUserProjectAccessByUser( + userId: string, + filters?: FilterListProjectUserAccess, + ): Promise { + TaskBase.checkUserId(userId); + + return await this.userAccessApi.listUserProjectAccess({ + userId, + ...filters, + }); + } + + /** + * Retrieves a list of all projects that a user has access to, along with their access levels and permissions for each + * project. This method provides an extended view of the user's access, which may include additional details about the + * projects and the user's permissions within those projects, making it easier to manage and review user access across + * multiple projects. + * @param userId - The ID of the user to list extended project access for. This should be a valid user ID that exists + * within the system. + * @param filters - Optional filters to apply to the list of extended project access, such as filtering by project ID + * or access level. + * @return A list of all projects that the specified user has access to, along with their access levels and + * permissions for each project. + * @throws An error if the user ID is invalid or if there is an issue with the API request to list the user's extended + * project access information. + */ + async listExtendedUserProjectAccess( + userId: string, + filters?: FilterListUserExtendedAccess, + ): Promise { + TaskBase.checkUserId(userId); + + return await this.grantsApi.listUserExtendedAccess({ userId, ...filters }); + } + + /** + * Revokes a user's access to a project. This method revokes the user's permissions for the specified project, + * effectively preventing them from accessing or collaborating on the project. Note that this does not delete the user + * from the system, but simply removes their access to the specified project. + * @param projectId - The ID of the project to revoke access from. This should be a valid project ID that exists + * within the system. + * @param userId - The ID of the user to revoke access for. This should be a valid user ID that exists within the + * system. + * @throws An error if the project ID or user ID is invalid, or if there is an issue with the API request to revoke + * the user's project access. + */ + async revokeUserProjectAccessByProject(projectId: string, userId: string): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkUserId(userId); + + await this.userAccessApi.removeProjectUserAccess({ projectId, userId }); + } + + /** + * Revokes a user's access to a project. This method revokes the user's permissions for the specified project, + * effectively preventing them from accessing or collaborating on the project. Note that this does not delete the user + * from the system, but simply removes their access to the specified project. + * @param userId - The ID of the user to revoke access for. This should be a valid user ID that exists within the + * system. + * @param projectId - The ID of the project to revoke access from. This should be a valid project ID that exists + * within the system. + * @throws An error if the user ID or project ID is invalid, or if there is an issue with the API request to revoke + * the user's project access. + */ + async revokeUserProjectAccessByUser(userId: string, projectId: string): Promise { + TaskBase.checkUserId(userId); + TaskBase.checkProjectId(projectId); + + await this.userAccessApi.removeUserProjectAccess({ projectId, userId }); + } + + /** + * Updates a user's access level and permissions for a specific project. This method allows you to modify the access + * permissions of a user for a project, which can be useful for managing user roles and ensuring that users have the + * appropriate level of access to perform their tasks within the project. By updating a user's project access, you can + * grant them additional permissions or restrict their access as needed. + * @param projectId - The ID of the project to update access for. This should be a valid project ID that exists within + * the system. + * @param userId - The ID of the user to update access for. This should be a valid user ID that exists within the + * system. + * @param access - The updated access details specifying the access levels and permissions to set for the user. This + * should include the new access level to grant for the user within the specified project. + * @throws An error if the project ID or user ID is invalid, if the access level is invalid, or if there is an issue + * with the API request to update the user's project access. + */ + async updateUserProjectAccessByProject( + projectId: string, + userId: string, + access: UpdateProjectUserAccessRequest, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkUserId(userId); + + if (!access || !access.permissions) { + throw new Error('At least one access level is required to update user access'); + } + + await this.userAccessApi.updateProjectUserAccess({ + projectId: projectId, + userId: userId, + updateProjectUserAccessRequest: access, + }); + } + + /** + * Updates a user's access level and permissions for a specific project. This method allows you to modify the access + * permissions of a user for a project, which can be useful for managing user roles and ensuring that users have the + * appropriate level of access to perform their tasks within the project. By updating a user's project access, you can + * grant them additional permissions or restrict their access as needed. + * @param userId - The ID of the user to update access for. This should be a valid user ID that exists within the + * system. + * @param projectId - The ID of the project to update access for. This should be a valid project ID that exists within + * the system. + * @param access - The updated access details specifying the access levels and permissions to set for the user. This + * should include the new access level to grant for the user within the specified project. + * @throws An error if the user ID or project ID is invalid, if the access level is invalid, or if there is an issue + * with the API request to update the user's project access. + */ + async updateUserProjectAccessByUser( + userId: string, + projectId: string, + access: UpdateProjectUserAccessRequest, + ): Promise { + TaskBase.checkUserId(userId); + TaskBase.checkProjectId(projectId); + + if (!access || !access.permissions) { + throw new Error('At least one access level is required to update user access'); + } + + await this.userAccessApi.updateUserProjectAccess({ + projectId: projectId, + userId: userId, + updateProjectUserAccessRequest: access, + }); + } + + /** + * Deletes a user's profile picture. This method removes the profile picture associated with the user's account, + * which may be useful for privacy reasons or if the user wants to update their profile picture. + * @param uuid - The UUID of the user whose profile picture is to be deleted. This should be a valid user UUID that + * exists within the system. + * @throws An error if the user UUID is invalid or if there is an issue with the API request to delete the user's + * profile picture. + */ + async deleteProfilePicture(uuid: string): Promise { + TaskBase.checkUserId(uuid); + + await this.userProfilesApi.deleteProfilePicture({ uuid }); + } + + /** + * Retrieves a user's address information. This method can be used to get the address details associated with a user's + * profile, which may include fields such as street address, city, state, postal code, and country. + * @param userId - The ID of the user to retrieve address information for. This should be a valid user ID that exists + * within the system. + * @return The address information associated with the specified user's profile, which may include fields such as + * street address, city, state, postal code, and country. + * @throws An error if the user ID is invalid or if there is an issue with the API request to retrieve the user's + * address. + */ + async getAddress(userId: string): Promise { + TaskBase.checkUserId(userId); + + return await this.userProfilesApi.getAddress({ userId }); + } + + /** + * Retrieves a user's profile information. This method can be used to get the details of a user's profile. + * @param userId - The ID of the user to retrieve profile information for. This should be a valid user ID that exists + * within the system. + * @return The profile information associated with the specified user, which may include details such as their + * username, full name, email address, profile picture URL, company, website, country, and other relevant information. + * @throws An error if the user ID is invalid or if there is an issue with the API request to retrieve the user's + * profile. + */ + async getProfile(userId: string): Promise { + TaskBase.checkUserId(userId); + + return await this.userProfilesApi.getProfile({ userId }); + } + + /** + * Lists all user profiles. This method retrieves a list of all user profiles in the system. + * @return A list of all user profiles, which may include details such as usernames, full names, email addresses, + * profile pictures, companies, websites, countries, and other relevant information. + * @throws An error if there is an issue with the API request to list user profiles. + */ + async listProfiles(): Promise { + return await this.userProfilesApi.listProfiles(); + } + + /** + * Updates a user's address information. This method allows you to modify the address details associated with a user's + * profile, which may include fields such as street address, city, state, postal code, and country. By updating a user's + * address information, you can ensure that their profile is accurate and up-to-date. + * @param userId - The ID of the user to update address information for. This should be a valid user ID that exists + * within the system. + * @param address - The updated address information to set for the user's profile, which may include fields such as + * street address, city, state, postal code, and country. + * @return Nothing if the address update is successful. If the user with the specified ID is not found, or if there is + * an error with the API request, an error will be thrown. + */ + async updateAddress(userId: string, address?: Address): Promise { + TaskBase.checkUserId(userId); + + await this.userProfilesApi.updateAddress({ + userId, + address, + }); + } + + /** + * Updates a user's profile information. This method allows you to modify the details of a user's profile. + * @param userId - The ID of the user to update profile information for. This should be a valid user ID that exists + * within the system. + * @param profile - The updated profile information to set for the user, which may include details such as their + * username, full name, email address, profile picture URL, company, website, country, and other relevant information. + * @throws An error if the user ID is invalid, if the profile information is invalid, or if there is an issue with the + * API request. + */ + async updateProfile(userId: string, profile?: UpdateProfileRequest): Promise { + TaskBase.checkUserId(userId); + + await this.userProfilesApi.updateProfile({ + userId, + updateProfileRequest: profile, + }); + } + + /** + * Creates a new API token for a user. This method allows you to generate an API token that can be used for + * authentication. + * @param userId - The ID of the user to create an API token for. This should be a valid user ID that exists within + * the system. + * @param name - The name to associate with the API token. This should be a descriptive name that helps identify the + * purpose of the token, such as "My APIToken" or "Token for CI/CD". Providing a name for the API token can help with + * managing and organizing tokens, especially if multiple tokens are created for the same user. + */ + async createApiToken(userId: string, name: string): Promise { + TaskBase.checkUserId(userId); + + if (!name) { + throw new Error('API token name is required'); + } + + await this.apiTokensApi.createApiToken({ + userId: userId, + createApiTokenRequest: { + name: name, + }, + }); + } + + /** + * Deletes an API token for a user. This method allows you to revoke an API token, which can be useful for security + * reasons or if the token is no longer needed. + * @param userId - The ID of the user to delete the API token for. This should be a valid user ID that exists within + * the system. + * @param tokenId - The ID of the API token to delete. This should be a valid API token ID that exists for the + * specified user. + * @throws An error if the user ID or token ID is invalid, or if there is an issue with the API request to delete the + * API token. + */ + async deleteApiToken(userId: string, tokenId: string): Promise { + TaskBase.checkUserId(userId); + TaskBase.checkApiTokenId(tokenId); + + await this.apiTokensApi.deleteApiToken({ + userId: userId, + tokenId: tokenId, + }); + } + + /** + * Retrieves a specific API token for a user. This method allows you to get the details of an API token. + * @param userId - The ID of the user to retrieve the API token for. This should be a valid user ID that exists within + * the system. + * @param tokenId - The ID of the API token to retrieve. This should be a valid API token ID that exists for the + * specified user. + * @return The details of the specified API token, which may include information such as the token's name, creation + * date, and other relevant metadata. + * @throws An error if the user ID or token ID is invalid, or if there is an issue with the API request to retrieve + * the API token. + */ + async getApiToken(userId: string, tokenId: string): Promise { + TaskBase.checkUserId(userId); + TaskBase.checkApiTokenId(tokenId); + + return await this.apiTokensApi.getApiToken({ + userId: userId, + tokenId: tokenId, + }); + } + + /** + * Lists all API tokens for a user. This method retrieves a list of all API tokens associated with a user's account, + * which can be useful for managing and reviewing the tokens that have been created. + * @param userId - The ID of the user to list API tokens for. This should be a valid user ID that exists within the + * system. + * @return A list of all API tokens associated with the specified user's account, which may include details such as + * the token's name, creation date, and other relevant metadata. + * @throws An error if the user ID is invalid or if there is an issue with the API request to list the user's API + * tokens. + */ + async listApiTokens(userId: string): Promise { + TaskBase.checkUserId(userId); + + return await this.apiTokensApi.listApiTokens({ userId }); + } + + /** + * Deletes a user's login connection for a specific provider. This method allows you to revoke a user's authentication + * connection for a particular login provider (e.g., Google, GitHub, etc.), which can be useful for security reasons or if + * the user wants to disconnect their account from that provider. + * @param provider - The name of the login provider to delete the connection for. This should be a valid provider name + * that exists within the system, such as "google", "github", etc. + * @param userId - The ID of the user to delete the login connection for. This should be a valid user ID that exists + * within the system. + * @throws An error if the provider name or user ID is invalid, or if there is an issue with the API request to delete + * the login connection. + */ + async deleteLoginConnection(provider: string, userId: string): Promise { + TaskBase.checkUserId(userId); + + if (!provider) { + throw new Error('Login provider is required'); + } + + await this.connectionsApi.deleteLoginConnection({ + userId, + provider, + }); + } + + /** + * Retrieves a user's login connection for a specific provider. This method allows you to get the details of a user's + * authentication connection for a particular login provider (e.g., Google, GitHub, etc.), which can be useful for + * managing and reviewing the connected accounts for a user. + * @param provider - The name of the login provider to retrieve the connection for. This should be a valid provider + * name that exists within the system, such as "google", "github", etc. + * @param userId - The ID of the user to retrieve the login connection for. This should be a valid user ID that exists + * within the system. + * @return The details of the user's login connection for the specified provider, which may include information such + * as the provider name, connection status, and other relevant metadata. + * @throws An error if the provider name or user ID is invalid, or if there is an issue with the API request to + * retrieve the login connection. + */ + async getLoginConnection(provider: string, userId: string): Promise { + TaskBase.checkUserId(userId); + + if (!provider) { + throw new Error('Login provider is required'); + } + + return await this.connectionsApi.getLoginConnection({ + userId, + provider, + }); + } + + /** + * Confirms a user's TOTP enrollment by verifying the provided TOTP secret and pass code. This method is used to + * complete the TOTP enrollment process for a user, ensuring that they have successfully set up their TOTP + * authentication method. By confirming the TOTP enrollment, the user can then use TOTP for + * two-factor authentication when logging in. + * @param userId - The ID of the user to confirm TOTP enrollment for. This should be a valid user ID that exists + * within the system. + * @param secret - The TOTP secret that was generated during the TOTP enrollment process. This should be a valid TOTP + * secret that was provided to the user when they initiated the TOTP enrollment. + * @param passCode - The TOTP pass code generated by the user's TOTP authenticator app using the provided secret. This + * should be a valid TOTP pass code that corresponds to the TOTP secret and is generated within the allowed time + * window. + * @return The result of the TOTP enrollment confirmation, which may include information about the success of the + * confirmation and any relevant metadata. If the TOTP enrollment is successfully confirmed, the user will be able to + * use TOTP for two-factor authentication when logging in. If the confirmation fails, an error will be thrown with + * details about the failure reason, such as an invalid secret, incorrect pass code, or other issues with the TOTP + * enrollment confirmation process. + * @throws An error if the user ID is invalid, if the TOTP secret or pass code is invalid, or if there is an issue + * with the API request to confirm the TOTP enrollment. + */ + async confirmTotpEnrollment( + userId: string, + secret: string, + passCode: string, + ): Promise { + TaskBase.checkUserId(userId); + + if (!secret) { + throw new Error('TOTP secret is required'); + } + + if (!passCode) { + throw new Error('TOTP pass code is required'); + } + + return await this.mfaApi.confirmTotpEnrollment({ + userId, + confirmTotpEnrollmentRequest: { + secret, + passcode: passCode, + }, + }); + } + + /** + * Retrieves a user's TOTP enrollment information. This method allows you to get the details of a user's TOTP + * enrollment. + * @param userId - The ID of the user to retrieve TOTP enrollment information for. This should be a valid user ID that + * exists within the system. + * @return The TOTP enrollment information associated with the specified user, which may include details such as the + * TOTP enrollment status, the TOTP secret (if applicable), and any relevant metadata about the user's TOTP + * enrollment. + * @throws An error if the user ID is invalid or if there is an issue with the API request to retrieve the user's TOTP + * enrollment information. + */ + async getTotpEnrollment(userId: string): Promise { + TaskBase.checkUserId(userId); + + return await this.mfaApi.getTotpEnrollment({ userId }); + } + + /** + * Withdraws a user's TOTP enrollment. This method allows you to revoke a user's TOTP enrollment. + * @param userId - The ID of the user to withdraw TOTP enrollment for. This should be a valid user ID that exists + * within the system. + * @throws An error if the user ID is invalid or if there is an issue with the API request to withdraw the user's TOTP + * enrollment. + */ + async withdrawTotpEnrollment(userId: string): Promise { + TaskBase.checkUserId(userId); + + await this.mfaApi.withdrawTotpEnrollment({ userId }); + } + + /** + * Recreates a user's MFA recovery codes. This method allows you to generate a new set of MFA recovery codes for a + * user, which can be useful if the user has lost their original recovery codes or if they want to invalidate their + * existing codes for security reasons. + * @param userId - The ID of the user to recreate MFA recovery codes for. This should be a valid user ID that exists + * within the system. + * @throws An error if the user ID is invalid or if there is an issue with the API request to recreate the user's MFA + * recovery codes. + */ + async recreateMfaRecoveryCodes(userId: string): Promise { + TaskBase.checkUserId(userId); + + await this.mfaApi.recreateRecoveryCodes({ userId }); + } + + /** + * Confirms a user's phone number by verifying the provided SID and confirmation code. + * @param sid - The SID of the phone number verification request. This should be a valid SID that was generated when + * the verification request was initiated. + * @param userId - The ID of the user to confirm the phone number for. This should be a valid user ID that exists + * within the system. + * @param code - The confirmation code sent to the user's phone number. This should be a valid confirmation code that + * was sent to the user's phone number as part of the verification process. The user should provide this code to + * confirm the phone number. + * @throws An error if the SID, user ID, or confirmation code is invalid, or if there is an issue with the API request + * to confirm the phone number. + */ + async confirmPhoneNumber(sid: string, userId: string, code: string): Promise { + TaskBase.checkUserId(userId); + + if (!sid) { + throw new Error('Phone number SID is required'); + } + + if (!code) { + throw new Error('Confirmation code is required'); + } + + await this.phoneNumberApi.confirmPhoneNumber({ + sid, + userId, + confirmPhoneNumberRequest: { code }, + }); + } + + /** + * Sends a verification code to a user's phone number via the specified channel (e.g., SMS, voice call) + * for phone number verification. + * @param userId - The ID of the user to verify the phone number for. This should be a valid user ID that exists + * within the system. + * @param channel - The channel through which to send the verification code. This should be a valid channel option, + * such as SMS or voice call. + * @param phoneNumber - The phone number to send the verification code to. This should be a valid phone number in the + * format expected by the system, which may include country code and other relevant formatting requirements. + * @throws An error if the user ID, channel, or phone number is invalid, or if there is an issue with the API request + * to send the verification code for phone number verification. + */ + async verifyPhoneNumber( + userId: string, + channel: VerifyPhoneNumberRequestChannelEnum, + phoneNumber: string, + ): Promise { + TaskBase.checkUserId(userId); + + if (!channel) { + throw new Error('Verification channel is required'); + } + + if (!phoneNumber) { + throw new Error('Phone number is required'); + } + + await this.phoneNumberApi.verifyPhoneNumber({ + userId, + verifyPhoneNumberRequest: { + channel, + phoneNumber, + }, + }); + } +} diff --git a/src/core/tasks/variable.ts b/src/core/tasks/variable.ts deleted file mode 100644 index ed7708f..0000000 --- a/src/core/tasks/variable.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class VariableTask extends TaskBase { - - constructor(protected readonly client: UpsunClient) { - super(client); - } - -} diff --git a/src/core/tasks/variables.ts b/src/core/tasks/variables.ts new file mode 100644 index 0000000..2453a9c --- /dev/null +++ b/src/core/tasks/variables.ts @@ -0,0 +1,312 @@ +import { ProjectVariablesApi } from '../../api/ProjectVariablesApi.js'; +import { + AcceptedResponse, + EnvironmentVariablesApi, + ProjectVariable, + ProjectVariablePatch, +} from '../../index.js'; +import { EnvironmentVariable } from '../../model/EnvironmentVariable.js'; +import { UpsunClient } from '../../upsun.js'; +import { EnvironmentVariableCreateParams, ProjectVariableCreateParams } from '../model.js'; +import { TaskBase } from './task_base.js'; + +export class VariablesTask extends TaskBase { + constructor( + protected readonly client: UpsunClient, + private projVarApi: ProjectVariablesApi, + private envVarApi: EnvironmentVariablesApi, + ) { + super(client); + } + + /** + * Creates a new project variable. This method allows you to create a new variable for a project. The variable can be used to store sensitive information, such as API keys or credentials, that can be accessed by tasks and deployments within the project. + * @param projectId The ID of the project for which the variable will be created. + * @param name The name of the variable. It must be unique within the project and can be prefixed with "env:" to indicate that it is an environment variable (e.g., "env:MY_VARIABLE") exposed in your container. + * @param value The value of the variable. For sensitive variables, the value will not be returned in API responses for security reasons, but it will be stored securely and can be used in tasks and deployments. + * @param params Optional additional parameters for creating the variable, such as whether it is sensitive or not. If the variable is marked as sensitive, its value will not be returned in API responses for security reasons, but it will be stored securely and can be used in tasks and deployments. + * @return A promise that resolves to an AcceptedResponse indicating that the variable creation request has been accepted. The actual creation of the variable may take some time, and you can check the status of the operation using the returned response. + */ + async createProjectVariable( + projectId: string, + name: string, + value: string, + params?: ProjectVariableCreateParams, + ): Promise { + TaskBase.checkProjectId(projectId); + + if (!name) { + throw new Error('Variable name is required'); + } + if (!value) { + throw new Error('Variable value is required'); + } + + return await this.projVarApi.createProjectsVariables({ + projectId, + projectVariableCreateInput: { name, value, ...params }, + }); + } + + /** + * Deletes a project variable by its ID. This method allows you to delete an existing variable from a project. Once + * deleted, the variable will no longer be available for use in tasks and deployments within the project. + * @param projectId The ID of the project from which the variable will be deleted. + * @param variableId The ID of the variable to delete. This should be a valid variable ID that exists within the + * project. + * @throws An error if the project ID or variable ID is invalid, or if there is an issue with the API request to + * delete the variable. + */ + async deleteProjectVariable(projectId: string, variableId: string): Promise { + TaskBase.checkProjectId(projectId); + VariablesTask.checkVariableId(variableId); + + await this.projVarApi.deleteProjectsVariables({ + projectId: projectId, + projectVariableId: variableId, + }); + } + + /** + * Get a project variable by its ID. + * + * @param projectId + * @param variableId The ID of the variable to retrieve. Its name is prefixed with "env:" for environment variables + * (e.g., "env:MY_VARIABLE"). In case of a sensitive variable, the value will not be returned for security + * reasons. + * @returns + */ + async getProjectVariable(projectId: string, variableId: string): Promise { + TaskBase.checkProjectId(projectId); + VariablesTask.checkVariableId(variableId); + + return await this.projVarApi.getProjectsVariables({ + projectId: projectId, + projectVariableId: variableId, + }); + } + + /** + * List all project variables for a given project. + * @param projectId The ID of the project to list variables for. + * @return An array of project variables associated with the specified project. + * @throws An error if the project ID is invalid or if there is an issue with the API request to list the project + * variables. + */ + async listProjectVariables(projectId: string): Promise { + TaskBase.checkProjectId(projectId); + + return await this.projVarApi.listProjectsVariables({ projectId: projectId }); + } + + /** + * Updates a project variable by its ID. + * @param projectId The ID of the project that the variable belongs to. + * @param variableId The ID of the variable to update. This should be a valid variable ID that exists within the + * project. + * @param params Optional parameters for updating the variable, such as a new name, value, or sensitivity status. + * If the variable is marked as sensitive, its value will not be returned in API responses for security reasons, but + * it will be stored securely and can be used in tasks and deployments. + * @return A promise that resolves to an AcceptedResponse indicating that the variable update request has been + * accepted. + * @throws An error if the project ID or variable ID is invalid, or if there is an issue with the API request to + * update the variable. + */ + async updateProjectVariable( + projectId: string, + variableId: string, + params?: ProjectVariablePatch, + ): Promise { + TaskBase.checkProjectId(projectId); + VariablesTask.checkVariableId(variableId); + + return await this.projVarApi.updateProjectsVariables({ + projectId: projectId, + projectVariableId: variableId, + projectVariablePatch: params || {}, + }); + } + + /** + * Creates a new environment variable for a specific environment within a project. + * @param projectId The ID of the project that the environment belongs to. + * @param environmentId The ID of the environment that the variable will be associated with. This should be a valid + * environment ID that exists within the project. + * @param name The name of the variable. It must be unique within the environment and should be prefixed with "env:" + * to indicate that it is an environment variable. + * @param value The value of the variable. For sensitive variables, the value will not be returned in API responses + * for security reasons, but it will be stored securely and can be used in tasks and deployments. + * @param params Optional additional parameters for creating the environment variable, such as whether it is sensitive + * or not. If the variable is marked as sensitive, its value will not be returned in API responses for security + * reasons, but it will be stored securely and can be used in tasks and deployments. + * @return A promise that resolves to an AcceptedResponse indicating that the environment variable creation request + * has been accepted. + * @throws An error if the project ID, environment ID, variable name, or variable value is invalid, or if there is an + * issue with the API request to create the environment variable. + */ + async createEnvironmentVariable( + projectId: string, + environmentId: string, + name: string, + value: string, + params?: EnvironmentVariableCreateParams, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + if (!name) { + throw new Error('Variable name is required'); + } + if (!value) { + throw new Error('Variable value is required'); + } + + return await this.envVarApi.createProjectsEnvironmentsVariables({ + projectId: projectId, + environmentId: environmentId, + environmentVariableCreateInput: { name, value, ...params }, + }); + } + + /** + * Deletes an environment variable by its ID. This method allows you to delete an existing variable from a specific + * environment within a project. Once deleted, the variable will no longer be available for use in tasks and + * deployments within that environment. + * @param projectId The ID of the project that the environment belongs to. + * @param environmentId The ID of the environment that the variable is associated with. + * @param variableId The ID of the variable to delete. This should be a valid variable ID that exists within the + * environment. + * @returns A promise that resolves to an AcceptedResponse indicating that the environment variable deletion request + * has been accepted. + * @throws An error if the project ID, environment ID, or variable ID is invalid, or if there is an issue with the API + * request to delete the environment variable. + */ + async deleteEnvironmentVariable( + projectId: string, + environmentId: string, + variableId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + VariablesTask.checkVariableId(variableId); + + return await this.envVarApi.deleteProjectsEnvironmentsVariables({ + projectId: projectId, + environmentId: environmentId, + variableId: variableId, + }); + } + + /** + * Get an environment variable by its ID. + * @param projectId + * @param environmentId + * @param variableId The ID of the variable to retrieve. Its name is prefixed with "env:" for environment variables + * (e.g., "env:MY_VARIABLE"). In case of a sensitive variable, the value will not be returned for security + * reasons. + * @returns A promise that resolves to the requested EnvironmentVariable. + * @throws An error if the project ID, environment ID, or variable ID is invalid, or if there is an issue with the API + * request to retrieve the environment variable. + */ + async getEnvironmentVariable( + projectId: string, + environmentId: string, + variableId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + VariablesTask.checkVariableId(variableId); + + return await this.envVarApi.getProjectsEnvironmentsVariables({ + projectId: projectId, + environmentId: environmentId, + variableId: variableId, + }); + } + + /** + * List all environment variables for a specific environment within a project. This method retrieves all variables + * that are associated with the specified environment, allowing you to view and manage the environment variables that + * are available for use in tasks and deployments within that environment. + * @param projectId The ID of the project that the environment belongs to. + * @param environmentId The ID of the environment to list variables for. This should be a valid environment ID that + * exists within the project. + * @return An array of environment variables associated with the specified environment. Each variable in the array + * includes details such as the variable's name, value (if not sensitive), and other relevant information. If there + * are no environment variables, an empty array is returned. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue with the API request to + * list environment variables. + */ + async listEnvironmentVariables( + projectId: string, + environmentId: string, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + + return await this.envVarApi.listProjectsEnvironmentsVariables({ + projectId: projectId, + environmentId: environmentId, + }); + } + + /** + * Updates an environment variable by its ID. This method allows you to update the details of an existing variable for + * a specific environment within a project. You can update the variable's name, value, and other properties. If the + * variable is marked as sensitive, its value will not be returned in API responses for security reasons, but it will + * be stored securely and can be used in tasks and deployments. + * @param projectId The ID of the project that the environment belongs to. + * @param environmentId The ID of the environment that the variable is associated with. + * @param variableId The ID of the variable to update. This should be a valid variable ID that exists within the + * environment. + * @param name The new name of the variable. It must be unique within the environment and should be prefixed with + * "env:" to indicate that it is an environment variable. + * @param value The new value of the variable. For sensitive variables, the value will not be returned in API + * responses. + * @param params Optional additional parameters for updating the environment variable, such as sensitivity status. + * If the variable is marked as sensitive, its value will not be returned in API responses for security reasons, + * but it will be stored securely and can be used in tasks and deployments. + * @return A promise that resolves to an AcceptedResponse indicating that the environment variable update request has + * been accepted. + * @throws An error if the project ID, environment ID, variable ID, variable name, or variable value is invalid, or + * if there is an issue with the API request to update the environment variable. + */ + async updateEnvironmentVariable( + projectId: string, + environmentId: string, + variableId: string, + name: string, + value: string, + params?: EnvironmentVariableCreateParams, + ): Promise { + TaskBase.checkProjectId(projectId); + TaskBase.checkEnvironmentId(environmentId); + VariablesTask.checkVariableId(variableId); + + if (!name) { + throw new Error('Variable name is required'); + } + if (!value) { + throw new Error('Variable value is required'); + } + + return await this.envVarApi.updateProjectsEnvironmentsVariables({ + projectId, + environmentId, + variableId, + environmentVariablePatch: { name, value, ...params }, + }); + } + + /** + * Checks if the provided variable ID is valid. This method is used to validate that a variable ID is provided and is + * in the correct format before making API requests that require a variable ID. If the variable ID is invalid, an + * error is thrown to prevent making an API request with an invalid variable ID. + * @param variableId + */ + static checkVariableId(variableId: string): void { + if (!variableId) { + throw new Error('Variable ID is required'); + } + } +} diff --git a/src/core/tasks/worker.ts b/src/core/tasks/worker.ts deleted file mode 100644 index 1e820f3..0000000 --- a/src/core/tasks/worker.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { UpsunClient } from "../../upsun.js"; -import { TaskBase } from "./taskBase.js"; - -export class WorkerTask extends TaskBase { - - constructor(protected readonly client: UpsunClient) { - super(client); - } - -} diff --git a/src/core/tasks/workers.ts b/src/core/tasks/workers.ts new file mode 100644 index 0000000..40b6a17 --- /dev/null +++ b/src/core/tasks/workers.ts @@ -0,0 +1,31 @@ +import { WorkersValue } from '../../index.js'; +import { UpsunClient } from '../../upsun.js'; +import { TaskBase } from './task_base.js'; + +export class WorkersTask extends TaskBase { + constructor(protected readonly client: UpsunClient) { + super(client); + } + + /** + * List the configuration of workers for an environment. This method retrieves the current deployment for the + * environment and returns the `workers` property from the deployment details, which contains the configuration of + * all workers for the environment. The returned object is a mapping of worker names to their respective configuration + * details. + * @param projectId - The ID of the project. + * @param environmentId - The ID of the environment. + * @return A mapping of worker names to their respective configuration details for the specified environment. If there + * are no workers configured, an empty object will be returned. + * @throws An error if the project ID or environment ID is invalid, or if there is an issue retrieving the deployment + * details. + */ + async list(projectId: string, environmentId: string): Promise<{ [key: string]: WorkersValue }> { + const currentDeployment = await this.client.environments.getDeployment( + projectId, + environmentId, + 'current', + ); + + return currentDeployment.workers; + } +} diff --git a/src/index.ts b/src/index.ts index 47c932d..db76b6a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ -/* tslint:disable */ -/* eslint-disable */ -export * from './upsun.js'; +export * from './core/index.js'; +export * from './api/index.js'; +export * from './model/index.js'; diff --git a/src/upsun.ts b/src/upsun.ts index 365887e..a341dd3 100644 --- a/src/upsun.ts +++ b/src/upsun.ts @@ -1,33 +1,85 @@ -import { Configuration, ConfigurationParameters } from "./apis-gen/index.js"; -import { OAuth2Client } from "./core/index.js"; - -import { ActivityTask } from "./core/tasks/activity.js"; -import { ApplicationTask } from "./core/tasks/application.js"; -import { BackupTask } from "./core/tasks/backup.js"; -import { CertificateTask } from "./core/tasks/certificate.js"; -import { DomainTask } from "./core/tasks/domain.js"; -import { EnvironementTask } from "./core/tasks/environment.js"; -import { MetricsTask } from "./core/tasks/metrics.js"; -import { MountTask } from "./core/tasks/mount.js"; -import { OperationTask } from "./core/tasks/operation.js"; -import { OrganizationTask } from "./core/tasks/organization.js"; -import { ProjectTask } from "./core/tasks/project.js"; -import { ResourcesTask } from "./core/tasks/resources.js"; -import { RouteTask } from "./core/tasks/route.js"; -import { ServiceTask } from "./core/tasks/service.js"; -import { SourceOperationTask } from "./core/tasks/source-operation.js"; -import { SshTask } from "./core/tasks/ssh.js"; -import { TeamTask } from "./core/tasks/team.js"; -import { UserTask } from "./core/tasks/user.js"; -import { VariableTask } from "./core/tasks/variable.js"; -import { WorkerTask } from "./core/tasks/worker.js"; - +import { + // Common + Configuration, + ConfigurationParameters, + HTTPHeaders, + Middleware, + OAuth2Client, + // Tasks + ActivitiesTask, + ApplicationsTask, + BackupsTask, + CertificatesTask, + DomainsTask, + EnvironmentsTask, + MetricsTask, + MountsTask, + OperationsTask, + OrganizationsTask, + ProjectsTask, + ResourcesTask, + RoutesTask, + ServicesTask, + SourceOperationsTask, + SshTask, + TeamsTask, + UsersTask, + VariablesTask, + WorkersTask, +} from './core/index.js'; +import { IntegrationsTask } from './core/tasks/integrations.js'; +import { RepositoriesTask } from './core/tasks/repositories.js'; +import { UsersInvitationsTask } from './core/tasks/users-invitations.js'; +import { + AddOnsApi, + ApiTokensApi, + AutoscalingApi, + CertManagementApi, + ConnectionsApi, + DeploymentApi, + DomainManagementApi, + EnvironmentActivityApi, + EnvironmentApi, + EnvironmentBackupsApi, + EnvironmentTypeApi, + EnvironmentVariablesApi, + GrantsApi, + InvoicesApi, + MfaApi, + OrdersApi, + OrganizationInvitationsApi, + OrganizationMembersApi, + OrganizationProjectsApi, + OrganizationsApi, + PhoneNumberApi, + ProfilesApi, + ProjectActivityApi, + ProjectApi, + ProjectInvitationsApi, + ProjectSettingsApi, + ProjectVariablesApi, + RecordsApi, + RepositoryApi, + RoutingApi, + RuntimeOperationsApi, + SourceOperationsApi, + SshKeysApi, + SubscriptionsApi, + SystemInformationApi, + TeamAccessApi, + TeamsApi, + ThirdPartyIntegrationsApi, + UserAccessApi, + UserProfilesApi, + UsersApi, + VouchersApi, +} from './index.js'; /** * Configuration interface for the Upsun API client. * This interface defines the structure of the configuration object * that is used to initialize the UpsunClient. - * + * * @interface UpsunConfig * @property {string} base_url - The base URL for the Upsun API. * @property {string} auth_url - The authentication URL for the Upsun API. @@ -51,12 +103,12 @@ export interface UpsunConfig { * defined in the UpsunConfig interface. */ export const DEFAULT_UPSUN_CONFIG: UpsunConfig = { - base_url: "https://api.upsun.com", // Default base URL for the Upsun API - auth_url: "https://auth.upsun.com", // Default authentication URL for the Upsun API - token_endpoint: "oauth2/token", - refresh_endpoint: "oauth2/token", - clientId: "sdk-node-client-id", -} + base_url: 'https://api.upsun.com', // Default base URL for the Upsun API + auth_url: 'https://auth.upsun.com', // Default authentication URL for the Upsun API + token_endpoint: 'oauth2/token', + refresh_endpoint: 'oauth2/token', + clientId: 'sdk-node-client-id', +}; /** * UpsunClient class for interacting with the Upsun API. @@ -64,7 +116,6 @@ export const DEFAULT_UPSUN_CONFIG: UpsunConfig = { * It uses the OAuth2Client for handling authentication. */ export class UpsunClient { - // Configuration for the Upsun API client. protected upsunConfig: UpsunConfig; public apiConfig: Configuration; @@ -73,31 +124,35 @@ export class UpsunClient { protected userId!: string; // Facades - Tasks. - public activity: ActivityTask; - public application: ApplicationTask; - public backup: BackupTask; - public certificate: CertificateTask; - public domain: DomainTask; - public environment: EnvironementTask; + public activities: ActivitiesTask; + public applications: ApplicationsTask; + public backups: BackupsTask; + public certificates: CertificatesTask; + public domains: DomainsTask; + public environments: EnvironmentsTask; + public integrations: IntegrationsTask; + public invitations: UsersInvitationsTask; public metrics: MetricsTask; - public mount: MountTask; - public operation: OperationTask; - public organization: OrganizationTask; - public project: ProjectTask; - public route: RouteTask; - public service: ServiceTask; - public sourceOperation: SourceOperationTask; + public mounts: MountsTask; + public operations: OperationsTask; + public organizations: OrganizationsTask; + public projects: ProjectsTask; + public repositories: RepositoriesTask; + public resources: ResourcesTask; + public routes: RoutesTask; + public services: ServicesTask; + public sourceOperations: SourceOperationsTask; public ssh: SshTask; - public team: TeamTask; - public user: UserTask; - public variable: VariableTask; - public worker: WorkerTask + public teams: TeamsTask; + public users: UsersTask; + public variables: VariablesTask; + public workers: WorkersTask; - public resource: ResourcesTask; + private authMiddleware: Middleware; /** * Constructor for the UpsunClient class. - * + * * @param config - Configuration object for the Upsun API client. */ constructor(config: UpsunConfig = DEFAULT_UPSUN_CONFIG) { @@ -106,19 +161,7 @@ export class UpsunClient { ...config, }; - // Initialize the API configuration with the base URL and access token. - // The access token is obtained through the getToken method. - // The getToken method is bound to the current instance of the UpsunClient. - const param: ConfigurationParameters = { - basePath: this.upsunConfig.base_url, - accessToken: this.getToken.bind(this), - }; - this.apiConfig = new Configuration(param); - if (this.upsunConfig.apiKey) { - // Initialize the OAuth2Client with the authentication URL, client ID, and API key. - // The OAuth2Client is responsible for handling the OAuth2 authentication flow. - // The auth_url is used to obtain the access token, and the clientId and apiKey are used for authentication. this.auth = new OAuth2Client( `${this.upsunConfig.auth_url}/${this.upsunConfig.token_endpoint}`, this.upsunConfig.clientId, @@ -126,71 +169,212 @@ export class UpsunClient { ); } + this.authMiddleware = this.createAuthRetryMiddleware(); + + const param: ConfigurationParameters = { + basePath: this.upsunConfig.base_url, + accessToken: this.getToken.bind(this), + middleware: [this.authMiddleware], + }; + this.apiConfig = new Configuration(param); + + // Init API classes only once + const addOnsApi = new AddOnsApi(this.apiConfig); + const autoscalingApi = new AutoscalingApi(this.apiConfig); + const apiTokensApi = new ApiTokensApi(this.apiConfig); + const certManagementApi = new CertManagementApi(this.apiConfig); + const connectionsApi = new ConnectionsApi(this.apiConfig); + const deploymentApi = new DeploymentApi(this.apiConfig); + const domainManagementApi = new DomainManagementApi(this.apiConfig); + const environmentApi = new EnvironmentApi(this.apiConfig); + const environmentBackupsApi = new EnvironmentBackupsApi(this.apiConfig); + const environmentTypeApi = new EnvironmentTypeApi(this.apiConfig); + const environmentVariablesApi = new EnvironmentVariablesApi(this.apiConfig); + const grantsApi = new GrantsApi(this.apiConfig); + const invoicesApi = new InvoicesApi(this.apiConfig); + const mfaApi = new MfaApi(this.apiConfig); + const ordersApi = new OrdersApi(this.apiConfig); + const organizationInvitationsApi = new OrganizationInvitationsApi(this.apiConfig); + const organizationMembersApi = new OrganizationMembersApi(this.apiConfig); + const organizationProjectsApi = new OrganizationProjectsApi(this.apiConfig); + const organizationsApi = new OrganizationsApi(this.apiConfig); + const phoneNumberApi = new PhoneNumberApi(this.apiConfig); + const profilesApi = new ProfilesApi(this.apiConfig); + const projectApi = new ProjectApi(this.apiConfig); + const projectInvitationsApi = new ProjectInvitationsApi(this.apiConfig); + const projectSettingsApi = new ProjectSettingsApi(this.apiConfig); + const projectVariablesApi = new ProjectVariablesApi(this.apiConfig); + const recordsApi = new RecordsApi(this.apiConfig); + const repositoryApi = new RepositoryApi(this.apiConfig); + const routingApi = new RoutingApi(this.apiConfig); + const runtimeOperationsApi = new RuntimeOperationsApi(this.apiConfig); + const sourceOperationsApi = new SourceOperationsApi(this.apiConfig); + const subscriptionsApi = new SubscriptionsApi(this.apiConfig); + const sshKeysApi = new SshKeysApi(this.apiConfig); + const systemInformationApi = new SystemInformationApi(this.apiConfig); + const teamAccessApi = new TeamAccessApi(this.apiConfig); + const teamsApi = new TeamsApi(this.apiConfig); + const thirdPartyIntegrationsApi = new ThirdPartyIntegrationsApi(this.apiConfig); + const userAccessApi = new UserAccessApi(this.apiConfig); + const userProfilesApi = new UserProfilesApi(this.apiConfig); + const usersApi = new UsersApi(this.apiConfig); + const vouchersApi = new VouchersApi(this.apiConfig); + // Initialize the commands tasks. - this.activity = new ActivityTask(this); - this.application = new ApplicationTask(this); - this.backup = new BackupTask(this); - this.certificate = new CertificateTask(this); - this.domain = new DomainTask(this); - this.environment = new EnvironementTask(this); + this.activities = new ActivitiesTask( + this, + new ProjectActivityApi(this.apiConfig), + new EnvironmentActivityApi(this.apiConfig), + ); + this.applications = new ApplicationsTask(this); + this.backups = new BackupsTask(this, environmentBackupsApi); + this.certificates = new CertificatesTask(this, certManagementApi); + this.domains = new DomainsTask(this, domainManagementApi); + this.environments = new EnvironmentsTask( + this, + environmentApi, + environmentTypeApi, + deploymentApi, + ); + this.integrations = new IntegrationsTask(this, thirdPartyIntegrationsApi); + this.invitations = new UsersInvitationsTask( + this, + organizationInvitationsApi, + projectInvitationsApi, + ); this.metrics = new MetricsTask(this); - this.mount = new MountTask(this); - this.operation = new OperationTask(this); - this.organization = new OrganizationTask(this); - this.project = new ProjectTask(this); - this.route = new RouteTask(this); - this.service = new ServiceTask(this); - this.sourceOperation = new SourceOperationTask(this); - this.ssh = new SshTask(this); - this.team = new TeamTask(this); - this.user = new UserTask(this); - this.variable = new VariableTask(this); - this.worker = new WorkerTask(this); - - this.resource = new ResourcesTask(this); + this.mounts = new MountsTask(this); + this.operations = new OperationsTask(this, runtimeOperationsApi); + this.organizations = new OrganizationsTask( + this, + organizationsApi, + organizationMembersApi, + subscriptionsApi, + invoicesApi, + mfaApi, + ordersApi, + profilesApi, + recordsApi, + vouchersApi, + addOnsApi, + ); + this.projects = new ProjectsTask( + this, + projectApi, + organizationProjectsApi, + subscriptionsApi, + projectSettingsApi, + ); + this.resources = new ResourcesTask(this, deploymentApi, autoscalingApi); + this.repositories = new RepositoriesTask(this, repositoryApi, systemInformationApi); + this.routes = new RoutesTask(this, routingApi); + this.services = new ServicesTask(this); + this.sourceOperations = new SourceOperationsTask(this, sourceOperationsApi); + this.ssh = new SshTask(this, sshKeysApi); + this.teams = new TeamsTask(this, teamsApi, teamAccessApi); + this.users = new UsersTask( + this, + usersApi, + userProfilesApi, + userAccessApi, + apiTokensApi, + connectionsApi, + grantsApi, + mfaApi, + phoneNumberApi, + ); + this.variables = new VariablesTask(this, projectVariablesApi, environmentVariablesApi); + this.workers = new WorkersTask(this); + } + + private createAuthRetryMiddleware(): Middleware { + type RetryableInit = RequestInit & { __upsunRetry?: boolean }; + + return { + post: async ({ fetch, url, init, response }): Promise => { + if (response.status !== 401) { + return response; + } + const retryInit: RetryableInit = { + ...(init || {}), + __upsunRetry: (init as RetryableInit)?.__upsunRetry, + }; + if (retryInit.__upsunRetry) { + return response; + } + retryInit.__upsunRetry = true; + if (!this.auth) { + return response; + } + await this.auth.exchangeCodeForToken(); + const token = await this.getToken(); + retryInit.headers = { + ...this.cloneHeaders(init.headers), + Authorization: `Bearer ${token}`, + }; + return fetch(url, retryInit); + }, + }; + } + + private cloneHeaders(headers?: HeadersInit): HTTPHeaders { + const normalized: HTTPHeaders = {}; + if (!headers) { + return normalized; + } + if (headers instanceof Headers) { + headers.forEach((value, key) => { + normalized[key] = value; + }); + } else if (Array.isArray(headers)) { + headers.forEach(([key, value]) => { + normalized[key] = value; + }); + } else { + Object.assign(normalized, headers); + } + return normalized; } /** * Authenticate the client using OAuth2. - * + * * This method exchanges the authorization code for an access token. * It uses the OAuth2Client to handle the authentication flow. * The access token is then used to authenticate API requests. * @returns {Promise} - Returns true if authentication is successful, false otherwise. */ async authenticate(): Promise { - - if (this.auth) { - return await this.auth.exchangeCodeForToken(); - } else { - console.log("API Key is not defined !"); - return false; + if (!this.auth) { + throw new Error('API Key is not defined. Cannot authenticate.'); } + return await this.auth.exchangeCodeForToken(); } - async getUserId(): Promise { + async getUserId(): Promise { if (this.userId == null) { - this.userId = (await this.user.me()).id; + this.userId = (await this.users.me()).id; } return this.userId; } - setBearerToken(token: string) { + setBearerToken(token: string): void { this.accessToken = token; } /** * Get the access token for authentication. */ - protected async getToken(name?: string, scopes?: string[]): Promise { + public async getToken(name?: string, scopes?: string[]): Promise { if (this.auth) { - return await this.auth.getAuthorization() + return await this.auth.getAuthorization(); } else if (this.accessToken) { - return `Bearer ${this.accessToken}`; + return `${this.accessToken}`; } else { - throw new Error("No authentication method available. Please provide an API key or set a bearer token."); + throw new Error( + 'No authentication method available. Please provide an API key or set a bearer token.', + ); } } - } diff --git a/templates/config.yaml b/templates/config.yaml new file mode 100644 index 0000000..aca5efa --- /dev/null +++ b/templates/config.yaml @@ -0,0 +1,67 @@ +generatorName: typescript-fetch +inputSpec: ./schema/openapispec-upsun.json +outputDir: src +packageName: upsun-client +templateDir: ./templates/node +generateSupportingFiles: true +verbose: false +generateAliasAsModel: true +apiTests: true +modelTests: true +apiDocs: false +modelDocs: false +authMethods: +isOAuth: true + +additionalProperties: + isApiKey: true + sdkName: upsun-sdk-node + sdkVersion: 0.1.0 + sdkDescription: The official Upsun SDK for Node.js + licenseName: MIT + artifactUrl: https://github.com/upsun/upsun-sdk-node + authorName: Upsun Advocacy Team + contributors: | + [ + { + "name": "Florent HUCK", + "email": "florent.huck@upsun.com" + }, + { + "name": "Mickael GAILLARD", + "email": "mickael.gaillard@upsun.com" + }, + { + "name": "Upsun Advocacy Team", + "homepage": "https://www.upsun.com" + } + ], + importFileExtension: .js + #Bug on OpenApiGenerator => fileNaming: kebab-case + enumPropertyNaming: UPPERCASE + modelPropertyNaming: camelCase + paramNaming: camelCase + supportsES6: true + withInterfaces: true + +files: + apis.mustache: + templateType: API + destinationFilename: .ts + folder: api + apis.index.mustache: + templateType: SupportingFiles + destinationFilename: index.ts + folder: api + models.mustache: + templateType: Model + destinationFilename: .ts + folder: model + models.index.mustache: + templateType: SupportingFiles + destinationFilename: index.ts + folder: model + runtime.mustache: + templateType: SupportingFiles + destinationFilename: runtime.ts + folder: core diff --git a/templates/node/ApiEntitiesRecord.mustache b/templates/node/ApiEntitiesRecord.mustache new file mode 100644 index 0000000..7c23f34 --- /dev/null +++ b/templates/node/ApiEntitiesRecord.mustache @@ -0,0 +1,26 @@ +import {Map, Record, RecordOf} from 'immutable'; + +import { +{{#models}} +{{#model}} +{{#isEntity}} + {{classname}}RecordEntity, +{{/isEntity}} +{{/model}} +{{/models}} +} from "./model/index{{importFileExtension}}" + +export const ApiEntitiesRecordProps = { + recType: "ApiEntitiesRecord" as "ApiEntitiesRecord", +{{#models}} +{{#model}} +{{#isEntity}} + {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}: ({{classname}}RecordEntity(), Map()), +{{/isEntity}} +{{/model}} +{{/models}} +}; + +export type ApiEntitiesRecordPropsType = typeof ApiEntitiesRecordProps; +export const ApiEntitiesRecord = Record(ApiEntitiesRecordProps, ApiEntitiesRecordProps.recType); +export type ApiEntitiesRecord = RecordOf; diff --git a/templates/node/ApiEntitiesReducer.mustache b/templates/node/ApiEntitiesReducer.mustache new file mode 100644 index 0000000..d1e7e52 --- /dev/null +++ b/templates/node/ApiEntitiesReducer.mustache @@ -0,0 +1,21 @@ +import {ApiEntitiesRecord} from "./ApiEntitiesRecord{{importFileExtension}}"; +import {ReducerBuilder} from "redux-ts-simple"; +import {normalizedEntities} from "./runtimeSagasAndRecords{{importFileExtension}}"; + +export const ApiEntitiesReducer = new ReducerBuilder(ApiEntitiesRecord()) + .on(normalizedEntities, (state, action): ApiEntitiesRecord => { + const {entities} = action.payload; + return state.withMutations(mutableState => { + for (const entityKey in entities) { + const entityMap = entities[entityKey]; + const currentEntityMap = mutableState.get(entityKey as any); + if (currentEntityMap) { + let mergedEntityMap = currentEntityMap.mergeDeep(entityMap); + if (!mergedEntityMap.equals(currentEntityMap)) { + mutableState.set(entityKey as any, mergedEntityMap); + } + } + } + }); + }) + .build(); diff --git a/templates/node/ApiEntitiesSelectors.mustache b/templates/node/ApiEntitiesSelectors.mustache new file mode 100644 index 0000000..f0997c4 --- /dev/null +++ b/templates/node/ApiEntitiesSelectors.mustache @@ -0,0 +1,5 @@ +export let getApiEntitiesState: (state: any) => any = (state: any) => state.app.apiEntities; + +export function setApiEntitiesStateGetter(getter: (state: any) => any) { // Use this to customize the location where you have placed your ApiEntitiesRecord in your project. + getApiEntitiesState = getter; +} \ No newline at end of file diff --git a/templates/node/README.mustache b/templates/node/README.mustache new file mode 100644 index 0000000..33dc3af --- /dev/null +++ b/templates/node/README.mustache @@ -0,0 +1,46 @@ +## {{npmName}}@{{npmVersion}} + +This generator creates TypeScript/JavaScript client that utilizes [Fetch API](https://fetch.spec.whatwg.org/). The generated Node module can be used in the following environments: + +Environment +* Node.js +* Webpack +* Browserify + +Language level +* ES5 - you must have a Promises/A+ library installed +* ES6 + +Module system +* CommonJS +* ES6 module system + +It can be used in both TypeScript and JavaScript. In TypeScript, the definition will be automatically resolved via `package.json`. ([Reference](https://www.typescriptlang.org/docs/handbook/declaration-files/consumption.html)) + +### Building + +To build and compile the typescript sources to javascript use: +``` +npm install +npm run build +``` + +### Publishing + +First build the package then run `npm publish` + +### Consuming + +navigate to the folder of your consuming project and run one of the following commands. + +_published:_ + +``` +npm install {{npmName}}@{{npmVersion}} --save +``` + +_unPublished (not recommended):_ + +``` +npm install PATH_TO_GENERATED_PACKAGE --save +``` diff --git a/templates/node/allSagas.mustache b/templates/node/allSagas.mustache new file mode 100644 index 0000000..62790c7 --- /dev/null +++ b/templates/node/allSagas.mustache @@ -0,0 +1,19 @@ +import {all, fork} from "redux-saga/effects"; + +import { +{{#apiInfo}} +{{#apis}} + {{#lambda.camelcase}}{{classFilename}}{{/lambda.camelcase}}AllSagas, +{{/apis}} +{{/apiInfo}} +} from "./index{{importFileExtension}}"; + +export function *allApiSagas() { + yield all([ +{{#apiInfo}} +{{#apis}} + fork({{#lambda.camelcase}}{{classFilename}}{{/lambda.camelcase}}AllSagas), +{{/apis}} +{{/apiInfo}} + ]); +} diff --git a/templates/node/apis.index.mustache b/templates/node/apis.index.mustache new file mode 100644 index 0000000..b26f8df --- /dev/null +++ b/templates/node/apis.index.mustache @@ -0,0 +1,14 @@ +{{#useSagaAndRecords}} +export * from './SagaApiManager{{importFileExtension}}' +export * from './allSagas{{importFileExtension}}' +{{/useSagaAndRecords}} +{{#apiInfo}} +{{#apis}} +{{#operations}} +export * from './{{ classFilename }}{{importFileExtension}}'; +{{#useSagaAndRecords}} +export * from './{{{ classFilename }}}Sagas{{importFileExtension}}'; +{{/useSagaAndRecords}} +{{/operations}} +{{/apis}} +{{/apiInfo}} diff --git a/templates/node/apis.mustache b/templates/node/apis.mustache new file mode 100644 index 0000000..47fc5b9 --- /dev/null +++ b/templates/node/apis.mustache @@ -0,0 +1,505 @@ +/* tslint:disable */ +/* eslint-disable */ +{{>licenseInfo}} + +import * as runtime from '../core/runtime{{importFileExtension}}'; +{{#imports.0}} +import type { + {{#imports}} + {{className}}, + {{/imports}} +} from '../model/index{{importFileExtension}}'; +{{^withoutRuntimeChecks}} +import { + {{#imports}} + {{className}}FromJSON, + {{className}}ToJSON, + {{/imports}} +} from '../model/index{{importFileExtension}}'; +{{/withoutRuntimeChecks}} +{{/imports.0}} + +{{#operations}} +{{#operation}} +{{#allParams.0}} +export interface {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request { +{{#allParams}} + {{paramName}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{#hasReadOnly}}Omit<{{{dataType}}}, {{#readOnlyVars}}'{{baseName}}'{{^-last}}|{{/-last}}{{/readOnlyVars}}>{{/hasReadOnly}}{{^hasReadOnly}}{{{dataType}}}{{/hasReadOnly}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}}; +{{/allParams}} +} + +{{/allParams.0}} +{{/operation}} +{{/operations}} +{{#withInterfaces}} +{{#operations}} +/** + * {{classname}} - interface + * {{#lambda.indented_1}}{{{unescapedDescription}}}{{/lambda.indented_1}} + * @export + * @interface {{classname}}Interface + */ +export interface {{classname}}Interface { +{{#operation}} + /** + * {{¬es}} + {{#summary}} + * @summary {{&summary}} + {{/summary}} + {{#allParams}} + * @param {{=<% %>=}}{<%&dataType%>}<%={{ }}=%> {{^required}}[{{/required}}{{paramName}}{{^required}}]{{/required}}{{description}} + {{/allParams}} + * @param {*} [options] Override http request option. + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + * @throws {RequiredError} + * @memberof {{classname}}Interface + */ + {{nickname}}Raw({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request, {{/allParams.0}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + + /** + {{#notes}} + * {{¬es}} + {{/notes}} + {{#summary}} + * {{&summary}} + {{/summary}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{^useSingleRequestParameter}} + {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}}, {{/allParams}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{{returnType}}}{{#returnType}}{{#isResponseOptional}} | null | undefined {{/isResponseOptional}}{{/returnType}}{{^returnType}}void{{/returnType}}>; + {{/useSingleRequestParameter}} + {{#useSingleRequestParameter}} + {{nickname}}({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request, {{/allParams.0}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{{returnType}}}{{#returnType}}{{#isResponseOptional}} | null | undefined {{/isResponseOptional}}{{/returnType}}{{^returnType}}void{{/returnType}}>; + {{/useSingleRequestParameter}} + +{{/operation}} +} + +{{/operations}} +{{/withInterfaces}} +{{#operations}} +/** + *{{#lambda.indented_star_1}} {{{unescapedDescription}}}{{/lambda.indented_star_1}} + */ +{{#withInterfaces}} +export class {{classname}} extends runtime.BaseAPI implements {{classname}}Interface { +{{/withInterfaces}} +{{^withInterfaces}} +export class {{classname}} extends runtime.BaseAPI { +{{/withInterfaces}} + + {{#operation}} + /** + {{#notes}} + * {{¬es}} + {{/notes}} + {{#summary}} + * {{&summary}} + {{/summary}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + async {{nickname}}Raw({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request, {{/allParams.0}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + {{#allParams}} + {{#required}} + if (requestParameters['{{paramName}}'] == null) { + throw new runtime.RequiredError( + '{{paramName}}', + 'Required parameter "{{paramName}}" was null or undefined when calling {{nickname}}().', + ); + } + + {{/required}} + {{/allParams}} + const queryParameters: any = {}; + + {{#queryParams}} + {{#isArray}} + if (requestParameters['{{paramName}}'] != null) { + {{#isCollectionFormatMulti}} + queryParameters['{{baseName}}'] = requestParameters['{{paramName}}']; + {{/isCollectionFormatMulti}} + {{^isCollectionFormatMulti}} + queryParameters['{{baseName}}'] = {{#uniqueItems}}Array.from({{/uniqueItems}}requestParameters['{{paramName}}']{{#uniqueItems}}){{/uniqueItems}}!.join(runtime.COLLECTION_FORMATS["{{collectionFormat}}"]); + {{/isCollectionFormatMulti}} + } + + {{/isArray}} + {{^isArray}} + if (requestParameters['{{paramName}}'] != null) { + {{#isDateTimeType}} + queryParameters['{{baseName}}'] = (requestParameters['{{paramName}}'] as any).toISOString(); + {{/isDateTimeType}} + {{^isDateTimeType}} + {{#isDateType}} + queryParameters['{{baseName}}'] = (requestParameters['{{paramName}}'] as any).toISOString().substring(0,10); + {{/isDateType}} + {{^isDateType}} + queryParameters['{{baseName}}'] = requestParameters['{{paramName}}']; + {{/isDateType}} + {{/isDateTimeType}} + } + + {{/isArray}} + {{/queryParams}} + const headerParameters: runtime.HTTPHeaders = {}; + + {{#bodyParam}} + {{^consumes}} + headerParameters['Content-Type'] = 'application/json'; + + {{/consumes}} + {{#consumes.0}} + headerParameters['Content-Type'] = '{{{mediaType}}}'; + + {{/consumes.0}} + {{/bodyParam}} + {{#headerParams}} + {{#isArray}} + if (requestParameters['{{paramName}}'] != null) { + headerParameters['{{baseName}}'] = {{#uniqueItems}}Array.from({{/uniqueItems}}requestParameters['{{paramName}}']{{#uniqueItems}}){{/uniqueItems}}!.join(runtime.COLLECTION_FORMATS["{{collectionFormat}}"]); + } + + {{/isArray}} + {{^isArray}} + if (requestParameters['{{paramName}}'] != null) { + headerParameters['{{baseName}}'] = String(requestParameters['{{paramName}}']); + } + + + {{/isArray}} + {{/headerParams}} + + {{#authMethods}} + {{#isBasic}} + {{#isBasicBasic}} + if (this.configuration && (this.configuration.username !== undefined || this.configuration.password !== undefined)) { + headerParameters["Authorization"] = "Basic " + btoa(this.configuration.username + ":" + this.configuration.password); + } + {{/isBasicBasic}} + {{#isBasicBearer}} + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("{{name}}", [{{#scopes}}"{{{scope}}}"{{^-last}}, {{/-last}}{{/scopes}}]); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + {{/isBasicBearer}} + {{/isBasic}} + {{#isApiKey}} + {{#isKeyInHeader}} + if (this.configuration && this.configuration.apiKey) { + headerParameters["{{keyParamName}}"] = await this.configuration.apiKey("{{keyParamName}}"); // {{name}} authentication + } + + {{/isKeyInHeader}} + {{#isKeyInQuery}} + if (this.configuration && this.configuration.apiKey) { + queryParameters["{{keyParamName}}"] = await this.configuration.apiKey("{{keyParamName}}"); // {{name}} authentication + } + + {{/isKeyInQuery}} + {{/isApiKey}} + {{#isOAuth}} + if (this.configuration && this.configuration.accessToken) { + // oauth required + headerParameters["Authorization"] = await this.configuration.accessToken("{{name}}", [{{#scopes}}"{{{scope}}}"{{^-last}}, {{/-last}}{{/scopes}}]); + } + + {{/isOAuth}} + {{/authMethods}} + {{#hasFormParams}} + const consumes: runtime.Consume[] = [ + {{#consumes}} + { contentType: '{{{mediaType}}}' }, + {{/consumes}} + ]; + // @ts-ignore: canConsumeForm may be unused + const canConsumeForm = runtime.canConsumeForm(consumes); + + let formParams: { append(param: string, value: any): any }; + let useForm = false; + {{#formParams}} + {{#isFile}} + // use FormData to transmit files using content-type "multipart/form-data" + useForm = canConsumeForm; + {{/isFile}} + {{/formParams}} + if (useForm) { + formParams = new FormData(); + } else { + formParams = new URLSearchParams(); + } + + {{#formParams}} + {{#isArray}} + if (requestParameters['{{paramName}}'] != null) { + {{#isCollectionFormatMulti}} + requestParameters['{{paramName}}'].forEach((element) => { + formParams.append('{{baseName}}{{#useSquareBracketsInArrayNames}}[]{{/useSquareBracketsInArrayNames}}', element as any); + }) + {{/isCollectionFormatMulti}} + {{^isCollectionFormatMulti}} + formParams.append('{{baseName}}{{#useSquareBracketsInArrayNames}}[]{{/useSquareBracketsInArrayNames}}', {{#uniqueItems}}Array.from({{/uniqueItems}}requestParameters['{{paramName}}']{{#uniqueItems}}){{/uniqueItems}}!.join(runtime.COLLECTION_FORMATS["{{collectionFormat}}"])); + {{/isCollectionFormatMulti}} + } + + {{/isArray}} + {{^isArray}} + if (requestParameters['{{paramName}}'] != null) { + {{#isDateTimeType}} + formParams.append('{{baseName}}', (requestParameters['{{paramName}}'] as any).toISOString()); + {{/isDateTimeType}} + {{^isDateTimeType}} + {{#isPrimitiveType}} + formParams.append('{{baseName}}', requestParameters['{{paramName}}'] as any); + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{#isEnumRef}} + formParams.append('{{baseName}}', requestParameters['{{paramName}}'] as any); + {{/isEnumRef}} + {{^isEnumRef}} + {{^withoutRuntimeChecks}} + formParams.append('{{baseName}}', new Blob([JSON.stringify({{returnType}}ToJSON(requestParameters['{{paramName}}']))], { type: "application/json", })); + {{/withoutRuntimeChecks}}{{#withoutRuntimeChecks}} + formParams.append('{{baseName}}', new Blob([JSON.stringify(requestParameters['{{paramName}}'])], { type: "application/json", })); + {{/withoutRuntimeChecks}} + {{/isEnumRef}} + {{/isPrimitiveType}} + {{/isDateTimeType}} + } + + {{/isArray}} + {{/formParams}} + {{/hasFormParams}} + + let urlPath = `{{{path}}}`; + {{#pathParams}} + {{#isDateTimeType}} + if (requestParameters['{{paramName}}'] instanceof Date) { + urlPath = urlPath.replace( + `{${'{{baseName}}'}}`, + encodeURIComponent(requestParameters['{{paramName}}'].toISOString()), + ); + } else { + urlPath = urlPath.replace( + `{${'{{baseName}}'}}`, + encodeURIComponent(String(requestParameters['{{paramName}}'])), + ); + } + {{/isDateTimeType}} + {{^isDateTimeType}} + {{#isDateType}} + if (requestParameters['{{paramName}}'] instanceof Date) { + urlPath = urlPath.replace( + `{${'{{baseName}}'}}`, + encodeURIComponent(requestParameters['{{paramName}}'].toISOString().substring(0,10), + ); + } else { + urlPath = urlPath.replace( + `{${'{{baseName}}'}}`, + encodeURIComponent(String(requestParameters['{{paramName}}'])), + ); + } + {{/isDateType}} + {{^isDateType}} + urlPath = urlPath.replace( + `{${'{{baseName}}'}}`, + encodeURIComponent(String(requestParameters['{{paramName}}'])), + ); + {{/isDateType}} + {{/isDateTimeType}} + {{/pathParams}} + + const response = await this.request( + { + path: urlPath, + method: '{{httpMethod}}', + headers: headerParameters, + query: queryParameters, + {{#hasBodyParam}} + {{#bodyParam}} + {{#isContainer}} + {{^withoutRuntimeChecks}} + body: requestParameters['{{paramName}}']{{#isArray}}{{#items}}{{^isPrimitiveType}}!.map({{datatype}}ToJSON){{/isPrimitiveType}}{{/items}}{{/isArray}}, + {{/withoutRuntimeChecks}} + {{#withoutRuntimeChecks}} + body: requestParameters['{{paramName}}'], + {{/withoutRuntimeChecks}} + {{/isContainer}} + {{^isContainer}} + {{^isPrimitiveType}} + {{^withoutRuntimeChecks}} + body: {{dataType}}ToJSON(requestParameters['{{paramName}}']), + {{/withoutRuntimeChecks}} + {{#withoutRuntimeChecks}} + body: requestParameters['{{paramName}}'], + {{/withoutRuntimeChecks}} + {{/isPrimitiveType}} + {{#isPrimitiveType}} + body: requestParameters['{{paramName}}'] as any, + {{/isPrimitiveType}} + {{/isContainer}} + {{/bodyParam}} + {{/hasBodyParam}} + {{#hasFormParams}} + body: formParams, + {{/hasFormParams}} + }, + initOverrides, + ); + + {{#returnType}} + {{#isResponseFile}} + return new runtime.BlobApiResponse(response); + {{/isResponseFile}} + {{^isResponseFile}} + {{#returnTypeIsPrimitive}} + {{#isMap}} + return new runtime.JSONApiResponse(response); + {{/isMap}} + {{#isArray}} + return new runtime.JSONApiResponse(response); + {{/isArray}} + {{#returnSimpleType}} + if (this.isJsonMime(response.headers.get('content-type'))) { + return new runtime.JSONApiResponse<{{returnType}}>(response); + } else { + return new runtime.TextApiResponse(response) as any; + } + {{/returnSimpleType}} + {{/returnTypeIsPrimitive}} + {{^returnTypeIsPrimitive}} + {{#isArray}} + return new runtime.JSONApiResponse(response{{^withoutRuntimeChecks}}, jsonValue => + {{#uniqueItems}}new Set({{/uniqueItems}}jsonValue.map({{returnBaseType}}FromJSON){{/withoutRuntimeChecks}}){{#uniqueItems}}){{/uniqueItems}}; + {{/isArray}} + {{^isArray}} + {{#isMap}} + return new runtime.JSONApiResponse(response{{^withoutRuntimeChecks}}, jsonValue => + runtime.mapValues(jsonValue, {{returnBaseType}}FromJSON){{/withoutRuntimeChecks}}, + ); + {{/isMap}} + {{^isMap}} + return new runtime.JSONApiResponse(response{{^withoutRuntimeChecks}}, jsonValue => + {{returnBaseType}}FromJSON(jsonValue){{/withoutRuntimeChecks}}, + ); + {{/isMap}} + {{/isArray}} + {{/returnTypeIsPrimitive}} + {{/isResponseFile}} + {{/returnType}} + {{^returnType}} + return new runtime.VoidApiResponse(response); + {{/returnType}} + } + + /** + {{#notes}} + * {{¬es}} + {{/notes}} + {{#summary}} + * {{&summary}} + {{/summary}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{^useSingleRequestParameter}} + async {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}}, {{/allParams}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{{returnType}}}{{#returnType}}{{#isResponseOptional}} | null | undefined {{/isResponseOptional}}{{/returnType}}{{^returnType}}void{{/returnType}}> { + {{#returnType}} + const response = await this.{{nickname}}Raw({{#allParams.0}}{ {{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}} }, {{/allParams.0}}initOverrides); + {{#isResponseOptional}} + switch (response.raw.status) { + {{#responses}} + {{#is2xx}} + case {{code}}: + return {{#dataType}}await response.value(){{/dataType}}{{^dataType}}null{{/dataType}}; + {{/is2xx}} + {{/responses}} + default: + return await response.value(); + } + {{/isResponseOptional}} + {{^isResponseOptional}} + return await response.value(); + {{/isResponseOptional}} + {{/returnType}} + {{^returnType}} + await this.{{nickname}}Raw({{#allParams.0}}{ {{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}} }, {{/allParams.0}}initOverrides); + {{/returnType}} + } + {{/useSingleRequestParameter}} + {{#useSingleRequestParameter}} + async {{nickname}}({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, {{/allParams.0}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{{returnType}}}{{#returnType}}{{#isResponseOptional}} | null | undefined {{/isResponseOptional}}{{/returnType}}{{^returnType}}void{{/returnType}}> { + {{#returnType}} + const response = await this.{{nickname}}Raw({{#allParams.0}}requestParameters, {{/allParams.0}}initOverrides); + {{#isResponseOptional}} + switch (response.raw.status) { + {{#responses}} + {{#is2xx}} + case {{code}}: + return {{#dataType}}await response.value(){{/dataType}}{{^dataType}}null{{/dataType}}; + {{/is2xx}} + {{/responses}} + default: + return await response.value(); + } + {{/isResponseOptional}} + {{^isResponseOptional}} + return await response.value(); + {{/isResponseOptional}} + {{/returnType}} + {{^returnType}} + await this.{{nickname}}Raw({{#allParams.0}}requestParameters, {{/allParams.0}}initOverrides); + {{/returnType}} + } + {{/useSingleRequestParameter}} + + {{/operation}} +} +{{/operations}} +{{#hasEnums}} + +{{#operations}} +{{#operation}} +{{#allParams}} +{{#isEnum}} +{{#stringEnums}} +/** + * @export + * @enum {string} + */ +export enum {{operationIdCamelCase}}{{enumName}} { +{{#allowableValues}} + {{#enumVars}} + {{{name}}} = {{{value}}}{{^-last}},{{/-last}} + {{/enumVars}} +{{/allowableValues}} +} +{{/stringEnums}} +{{^stringEnums}} +/** + * @export + */ +export const {{operationIdCamelCase}}{{enumName}} = { +{{#allowableValues}} + {{#enumVars}} + {{{name}}}: {{{value}}}{{^-last}},{{/-last}} + {{/enumVars}} +{{/allowableValues}} +} as const; +export type {{operationIdCamelCase}}{{enumName}} = typeof {{operationIdCamelCase}}{{enumName}}[keyof typeof {{operationIdCamelCase}}{{enumName}}]; +{{/stringEnums}} +{{/isEnum}} +{{/allParams}} +{{/operation}} +{{/operations}} +{{/hasEnums}} \ No newline at end of file diff --git a/templates/node/gitignore b/templates/node/gitignore new file mode 100644 index 0000000..149b576 --- /dev/null +++ b/templates/node/gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist diff --git a/templates/node/index.mustache b/templates/node/index.mustache new file mode 100644 index 0000000..32ad33c --- /dev/null +++ b/templates/node/index.mustache @@ -0,0 +1,15 @@ +export * from './core/runtime{{importFileExtension}}'; +{{#useSagaAndRecords}} +export * from './runtimeSagasAndRecords{{importFileExtension}}'; +export * from './ApiEntitiesRecord{{importFileExtension}}'; +export * from './ApiEntitiesReducer{{importFileExtension}}'; +export * from './ApiEntitiesSelectors{{importFileExtension}}'; +{{/useSagaAndRecords}} +{{#apiInfo}} +{{#apis.0}} +export * from './api/index{{importFileExtension}}'; +{{/apis.0}} +{{/apiInfo}} +{{#models.0}} +export * from './model/index{{importFileExtension}}'; +{{/models.0}} diff --git a/templates/node/licenseInfo.mustache b/templates/node/licenseInfo.mustache new file mode 100644 index 0000000..b52507a --- /dev/null +++ b/templates/node/licenseInfo.mustache @@ -0,0 +1,8 @@ +/** + * {{{appName}}} + * The official Upsun SDK for NodeJS (TS). This SDK provides a NodeJS (TypeScript) interface that maps to the Upsun CLI commands. + * For more information, read [project](https://github.com/upsun/upsun-sdk-node). + * + * NOTE: This class is auto generated by OpenAPI Generator (https://github.com/OpenAPITools/openapi-generator). + * Do not edit the class manually. + */ \ No newline at end of file diff --git a/templates/node/modelEnum.mustache b/templates/node/modelEnum.mustache new file mode 100644 index 0000000..e264bbc --- /dev/null +++ b/templates/node/modelEnum.mustache @@ -0,0 +1,28 @@ +{{>modelEnumInterfaces}} + +export function instanceOf{{classname}}(value: any): boolean { + for (const key in {{classname}}) { + if (Object.prototype.hasOwnProperty.call({{classname}}, key)) { + if ({{classname}}[key as keyof typeof {{classname}}] === value) { + return true; + } + } + } + return false; +} + +export function {{classname}}FromJSON(json: any): {{classname}} { + return {{classname}}FromJSONTyped(json, false); +} + +export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boolean): {{classname}} { + return json as {{classname}}; +} + +export function {{classname}}ToJSON(value?: {{classname}} | null): any { + return value as any; +} + +export function {{classname}}ToJSONTyped(value: any, ignoreDiscriminator: boolean): {{classname}} { + return value as {{classname}}; +} diff --git a/templates/node/modelEnumInterfaces.mustache b/templates/node/modelEnumInterfaces.mustache new file mode 100644 index 0000000..08bd178 --- /dev/null +++ b/templates/node/modelEnumInterfaces.mustache @@ -0,0 +1,37 @@ +{{#stringEnums}} +/** + * {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}} + * @export + * @enum {string} + */ +export enum {{classname}} { +{{#allowableValues}} +{{#enumVars}} + {{#enumDescription}} + /** + * {{enumDescription}} + */ + {{/enumDescription}} + {{{name}}} = {{{value}}}{{^-last}},{{/-last}} +{{/enumVars}} +{{/allowableValues}} +} +{{/stringEnums}}{{^stringEnums}} +/** + * {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}} + * @export + */ +export const {{classname}} = { +{{#allowableValues}} +{{#enumVars}} + {{#enumDescription}} + /** + * {{enumDescription}} + */ + {{/enumDescription}} + {{{name}}}: {{{value}}}{{^-last}},{{/-last}} +{{/enumVars}} +{{/allowableValues}} +} as const; +export type {{classname}} = typeof {{classname}}[keyof typeof {{classname}}]; +{{/stringEnums}} \ No newline at end of file diff --git a/templates/node/modelGeneric.mustache b/templates/node/modelGeneric.mustache new file mode 100644 index 0000000..485f4d3 --- /dev/null +++ b/templates/node/modelGeneric.mustache @@ -0,0 +1,252 @@ +import { mapValues } from '../core/runtime{{importFileExtension}}'; +{{#hasImports}} +{{#tsImports}} +import type { {{{classname}}} } from './{{filename}}{{importFileExtension}}'; +import { + {{classname}}FromJSON, + {{classname}}FromJSONTyped, + {{classname}}ToJSON, + {{classname}}ToJSONTyped, +} from './{{filename}}{{importFileExtension}}'; +{{/tsImports}} +{{/hasImports}} +{{#vendorExtensions.x-uniqueDiscriminatorModels}} +import { type {{.}}, {{.}}FromJSONTyped, {{.}}ToJSON, {{.}}ToJSONTyped } from './{{.}}{{importFileExtension}}'; +{{/vendorExtensions.x-uniqueDiscriminatorModels}} + +{{>modelGenericInterfaces}} + +/** + * Check if a given object implements the {{classname}} interface. + */ +export function instanceOf{{classname}}(value: object): value is {{classname}} { + {{#vars}} + {{#required}} + if (!('{{name}}' in value) || value['{{name}}'] === undefined) return false; + {{/required}} + {{/vars}} + return true; +} + +export function {{classname}}FromJSON(json: any): {{classname}} { + return {{classname}}FromJSONTyped(json, false); +} + +export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boolean): {{classname}} { + {{#hasVars}} + if (json == null) { + return json; + } +{{#discriminator}} + if (!ignoreDiscriminator) { +{{#discriminator.mappedModels}} + if (json['{{discriminator.propertyBaseName}}'] === '{{mappingName}}') { + return {{modelName}}FromJSONTyped(json, ignoreDiscriminator) as {{classname}}; + } +{{/discriminator.mappedModels}} + } +{{/discriminator}} + return { + {{#parent}}...{{{.}}}FromJSONTyped(json, true),{{/parent}} + {{#additionalPropertiesType}} + ...json, + {{/additionalPropertiesType}} + {{#vars}} + {{#isPrimitiveType}} + {{#isArray}} + {{#uniqueItems}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}{{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}new Set(json['{{baseName}}']), + {{/uniqueItems}} + {{^uniqueItems}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}{{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}json['{{baseName}}'], + {{/uniqueItems}} + {{/isArray}} + {{^isArray}} + {{#isDateType}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}new Date(json['{{baseName}}'])), + {{/isDateType}} + {{#isDateTimeType}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}new Date(json['{{baseName}}'])), + {{/isDateTimeType}} + {{^isDateType}} + {{^isDateTimeType}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}json['{{baseName}}'], + {{/isDateTimeType}} + {{/isDateType}} + {{/isArray}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{#isArray}} + {{#uniqueItems}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}new Set((json['{{baseName}}'] as Array).map({{#items}}{{datatype}}{{/items}}FromJSON))), + {{/uniqueItems}} + {{^uniqueItems}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}(json['{{baseName}}'] as Array).map({{#items}}{{datatype}}{{/items}}FromJSON)), + {{/uniqueItems}} + {{/isArray}} + {{#isMap}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}mapValues(json['{{baseName}}'], {{#items}}{{datatype}}{{/items}}FromJSON)), + {{/isMap}} + {{^isArray}} + {{^isMap}} + {{^isFreeFormObject}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}{{datatype}}FromJSON(json['{{baseName}}']), + {{/isFreeFormObject}} + {{#isFreeFormObject}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}json['{{baseName}}'], + {{/isFreeFormObject}} + {{/isMap}} + {{/isArray}} + {{/isPrimitiveType}} + {{/vars}} + }; + {{/hasVars}} + {{^hasVars}} + return json; + {{/hasVars}} +} + +export function {{classname}}ToJSON(json: any): {{classname}} { + return {{classname}}ToJSONTyped(json, false); +} + +export function {{classname}}ToJSONTyped(value?: {{#hasReadOnly}}Omit<{{classname}}, {{#readOnlyVars}}'{{baseName}}'{{^-last}}|{{/-last}}{{/readOnlyVars}}>{{/hasReadOnly}}{{^hasReadOnly}}{{classname}}{{/hasReadOnly}} | null, ignoreDiscriminator: boolean = false): any { + {{#hasVars}} + if (value == null) { + return value; + } + {{#discriminator}} + + if (!ignoreDiscriminator) { + switch (value['{{discriminator.propertyName}}']) { + {{#discriminator.mappedModels}} + case '{{mappingName}}': + return {{modelName}}ToJSONTyped(value as {{modelName}}, ignoreDiscriminator) as {{classname}}; + {{/discriminator.mappedModels}} + default: + return value; + } + } + {{/discriminator}} + + return { + {{#parent}}...{{{.}}}ToJSONTyped(value, true),{{/parent}} + {{#additionalPropertiesType}} + ...value, + {{/additionalPropertiesType}} + {{#vars}} + {{^isReadOnly}} + {{#isPrimitiveType}} + {{#isDateType}} + '{{baseName}}': {{^required}}{{#isNullable}}value['{{name}}'] === null ? null : {{/isNullable}}{{^isNullable}}value['{{name}}'] == null ? undefined : {{/isNullable}}{{/required}}((value['{{name}}']{{#isNullable}} as any{{/isNullable}}){{^required}}{{#isNullable}}?{{/isNullable}}{{/required}}.toISOString().substring(0,10)), + {{/isDateType}} + {{#isDateTimeType}} + '{{baseName}}': {{^required}}{{#isNullable}}value['{{name}}'] === null ? null : {{/isNullable}}{{^isNullable}}value['{{name}}'] == null ? undefined : {{/isNullable}}{{/required}}((value['{{name}}']{{#isNullable}} as any{{/isNullable}}){{^required}}{{#isNullable}}?{{/isNullable}}{{/required}}.toISOString()), + {{/isDateTimeType}} + {{#isArray}} + '{{baseName}}': {{#uniqueItems}}{{^required}}value['{{name}}'] == null ? undefined : {{/required}}{{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}Array.from(value['{{name}}'] as Set){{/uniqueItems}}{{^uniqueItems}}value['{{name}}']{{/uniqueItems}}, + {{/isArray}} + {{^isDateType}} + {{^isDateTimeType}} + {{^isArray}} + '{{baseName}}': value['{{name}}'], + {{/isArray}} + {{/isDateTimeType}} + {{/isDateType}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{#isArray}} + {{#uniqueItems}} + '{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}Array.from(value['{{name}}'] as Set).map({{#items}}{{datatype}}{{/items}}ToJSON)), + {{/uniqueItems}} + {{^uniqueItems}} + '{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}(value['{{name}}'] as Array).map({{#items}}{{datatype}}{{/items}}ToJSON)), + {{/uniqueItems}} + {{/isArray}} + {{#isMap}} + '{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}mapValues(value['{{name}}'], {{#items}}{{datatype}}{{/items}}ToJSON)), + {{/isMap}} + {{^isArray}} + {{^isMap}} + {{^isFreeFormObject}} + '{{baseName}}': {{datatype}}ToJSON(value['{{name}}']), + {{/isFreeFormObject}} + {{#isFreeFormObject}} + '{{baseName}}': value['{{name}}'], + {{/isFreeFormObject}} + {{/isMap}} + {{/isArray}} + {{/isPrimitiveType}} + {{/isReadOnly}} + {{/vars}} + }; + {{/hasVars}} + {{^hasVars}} + return value; + {{/hasVars}} +} +{{#validationAttributes}} + +export const {{classname}}PropertyValidationAttributesMap: { + [property: string]: { + maxLength?: number, + minLength?: number, + pattern?: string, + maximum?: number, + exclusiveMaximum?: boolean, + minimum?: number, + exclusiveMinimum?: boolean, + multipleOf?: number, + maxItems?: number, + minItems?: number, + uniqueItems?: boolean + } +} = { +{{#vars}} +{{#hasValidation}} + {{name}}: { + {{#maxLength}} + maxLength: {{maxLength}}, + {{/maxLength}} + {{#minLength}} + minLength: {{minLength}}, + {{/minLength}} + {{#pattern}} + pattern: '{{pattern}}', + {{/pattern}} + {{#maximum}} + maximum: {{maximum}}, + exclusiveMaximum: {{exclusiveMaximum}}, + {{/maximum}} + {{#minimum}} + minimum: {{minimum}}, + exclusiveMinimum: {{exclusiveMinimum}}, + {{/minimum}} + {{#multipleOf}} + multipleOf: {{multipleOf}}, + {{/multipleOf}} + {{#maxItems}} + maxItems: {{maxItems}}, + {{/maxItems}} + {{#minItems}} + minItems: {{minItems}}, + {{/minItems}} + {{#isArray}} + uniqueItems: {{uniqueItems}}, + {{/isArray}} + }, +{{/hasValidation}} +{{/vars}} +} +{{#isAdditionalPropertiesTrue}} + +export const {{classname}}AdditionalPropertiesValidationAttributes: { maxProperties?: number, minProperties?: number } = { + {{#maxProperties}} + maxProperties: {{maxProperties}}, + {{/maxProperties}} + {{#minProperties}} + minProperties: {{minProperties}}, + {{/minProperties}} +} +{{/isAdditionalPropertiesTrue}} +{{/validationAttributes}} diff --git a/templates/node/modelGenericInterfaces.mustache b/templates/node/modelGenericInterfaces.mustache new file mode 100644 index 0000000..bbdb210 --- /dev/null +++ b/templates/node/modelGenericInterfaces.mustache @@ -0,0 +1,50 @@ +/** + * {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}} + * @export + * @interface {{classname}} + */ +export interface {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{ +{{#additionalPropertiesType}} + [key: string]: {{{additionalPropertiesType}}}{{#hasVars}} | any{{/hasVars}}; +{{/additionalPropertiesType}} +{{#vars}} + /** + * {{#lambda.indented_star_4}}{{{unescapedDescription}}}{{/lambda.indented_star_4}} + * @type {{=<% %>=}}{<%&datatype%>}<%={{ }}=%> + * @memberof {{classname}} + {{#deprecated}} + * @deprecated + {{/deprecated}} + */ + {{#isReadOnly}}readonly {{/isReadOnly}}{{name}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}}; +{{/vars}} +}{{#hasEnums}} + +{{#vars}} +{{#isEnum}} +{{#stringEnums}} +/** + * @export + * @enum {string} + */ +export enum {{classname}}{{enumName}} { +{{#allowableValues}} + {{#enumVars}} + {{{name}}} = {{{value}}}{{^-last}},{{/-last}} + {{/enumVars}} +{{/allowableValues}} +} +{{/stringEnums}}{{^stringEnums}} +/** + * @export + */ +export const {{classname}}{{enumName}} = { +{{#allowableValues}} + {{#enumVars}} + {{{name}}}: {{{value}}}{{^-last}},{{/-last}} + {{/enumVars}} +{{/allowableValues}} +} as const; +export type {{classname}}{{enumName}} = typeof {{classname}}{{enumName}}[keyof typeof {{classname}}{{enumName}}]; +{{/stringEnums}} +{{/isEnum}}{{/vars}}{{/hasEnums}} \ No newline at end of file diff --git a/templates/node/modelOneOf.mustache b/templates/node/modelOneOf.mustache new file mode 100644 index 0000000..116415c --- /dev/null +++ b/templates/node/modelOneOf.mustache @@ -0,0 +1,109 @@ +{{#hasImports}} +{{#imports}} +import type { {{{.}}} } from './{{.}}{{importFileExtension}}'; +import { + instanceOf{{{.}}}, + {{{.}}}FromJSON, + {{{.}}}FromJSONTyped, + {{{.}}}ToJSON, +} from './{{.}}{{importFileExtension}}'; +{{/imports}} + +{{/hasImports}} +{{>modelOneOfInterfaces}} + +export function {{classname}}FromJSON(json: any): {{classname}} { + return {{classname}}FromJSONTyped(json, false); +} + +export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boolean): {{classname}} { + if (json == null) { + return json; + } +{{#discriminator}} + switch (json['{{discriminator.propertyBaseName}}']) { +{{#discriminator.mappedModels}} + case '{{mappingName}}': + return Object.assign({}, {{modelName}}FromJSONTyped(json, true), { {{discriminator.propertyName}}: '{{mappingName}}' } as const); +{{/discriminator.mappedModels}} + default: + return json; + } +{{/discriminator}} +{{^discriminator}} + {{#oneOfModels}} + {{#-first}} + if (typeof json !== 'object') { + return json; + } + {{/-first}} + if (instanceOf{{{.}}}(json)) { + return {{{.}}}FromJSONTyped(json, true); + } + {{/oneOfModels}} + {{#oneOfArrays}} + {{#-first}} + if (Array.isArray(json)) { + if (json.every(item => typeof item === 'object')) { + {{/-first}} + if (json.every(item => instanceOf{{{.}}}(item))) { + return json.map(value => {{{.}}}FromJSONTyped(value, true)); + } + {{#-last}} + } + return json; + } + {{/-last}} + {{/oneOfArrays}} + + return {} as any; +{{/discriminator}} +} + +export function {{classname}}ToJSON(json: any): any { + return {{classname}}ToJSONTyped(json, false); +} + +export function {{classname}}ToJSONTyped(value?: {{classname}} | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } +{{#discriminator}} + switch (value['{{discriminator.propertyName}}']) { +{{#discriminator.mappedModels}} + case '{{mappingName}}': + return Object.assign({}, {{modelName}}ToJSON(value), { {{discriminator.propertyName}}: '{{mappingName}}' } as const); +{{/discriminator.mappedModels}} + default: + return json; + } +{{/discriminator}} +{{^discriminator}} + {{#oneOfModels}} + {{#-first}} + if (typeof value !== 'object') { + return value; + } + {{/-first}} + if (instanceOf{{{.}}}(value)) { + return {{{.}}}ToJSON(value as {{{.}}}); + } + {{/oneOfModels}} + {{#oneOfArrays}} + {{#-first}} + if (Array.isArray(value)) { + if (value.every(item => typeof item === 'object')) { + {{/-first}} + if (value.every(item => instanceOf{{{.}}}(item))) { + return value.map(value => {{{.}}}ToJSON(value as {{{.}}})); + } + {{#-last}} + } + return value; + } + {{/-last}} + {{/oneOfArrays}} + + return {}; +{{/discriminator}} +} diff --git a/templates/node/modelOneOfInterfaces.mustache b/templates/node/modelOneOfInterfaces.mustache new file mode 100644 index 0000000..ee4d1fc --- /dev/null +++ b/templates/node/modelOneOfInterfaces.mustache @@ -0,0 +1,6 @@ +/** + * @type {{classname}} + * {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}} + * @export + */ +export type {{classname}} = {{#discriminator}}{{#mappedModels}}{ {{discriminator.propertyName}}: '{{mappingName}}' } & {{modelName}}{{^-last}} | {{/-last}}{{/mappedModels}}{{/discriminator}}{{^discriminator}}{{#oneOf}}{{{.}}}{{^-last}} | {{/-last}}{{/oneOf}}{{/discriminator}}; \ No newline at end of file diff --git a/templates/node/models.index.mustache b/templates/node/models.index.mustache new file mode 100644 index 0000000..4f380d5 --- /dev/null +++ b/templates/node/models.index.mustache @@ -0,0 +1,27 @@ +{{#models}} +{{#model}} +{{^withoutRuntimeChecks}} +export * from './{{{ classFilename }}}{{importFileExtension}}'; +{{#useSagaAndRecords}} +{{^isEnum}} +export * from './{{{ classFilename }}}Record{{importFileExtension}}'; +{{/isEnum}} +{{/useSagaAndRecords}} +{{/withoutRuntimeChecks}} +{{#withoutRuntimeChecks}} +{{#isEnum}} +{{>modelEnumInterfaces}} +{{/isEnum}} +{{^isEnum}} +{{#oneOf}} +{{#-first}} +{{>modelOneOfInterfaces}} +{{/-first}} +{{/oneOf}} +{{^oneOf}} +{{>modelGenericInterfaces}} +{{/oneOf}} +{{/isEnum}} +{{/withoutRuntimeChecks}} +{{/model}} +{{/models}} diff --git a/templates/node/models.mustache b/templates/node/models.mustache new file mode 100644 index 0000000..20135a8 --- /dev/null +++ b/templates/node/models.mustache @@ -0,0 +1,20 @@ +/* tslint:disable */ +/* eslint-disable */ +{{>licenseInfo}} +{{#models}} +{{#model}} +{{#isEnum}} +{{>modelEnum}} +{{/isEnum}} +{{^isEnum}} +{{#oneOf}} +{{#-first}} +{{>modelOneOf}} +{{/-first}} +{{/oneOf}} +{{^oneOf}} +{{>modelGeneric}} +{{/oneOf}} +{{/isEnum}} +{{/model}} +{{/models}} diff --git a/templates/node/npmignore.mustache b/templates/node/npmignore.mustache new file mode 100644 index 0000000..42061c0 --- /dev/null +++ b/templates/node/npmignore.mustache @@ -0,0 +1 @@ +README.md \ No newline at end of file diff --git a/templates/node/recordGeneric.mustache b/templates/node/recordGeneric.mustache new file mode 100644 index 0000000..09b3d74 --- /dev/null +++ b/templates/node/recordGeneric.mustache @@ -0,0 +1,295 @@ +import {ApiRecordUtils, knownRecordFactories{{#returnPassthrough}}, appFromJS, NormalizedRecordEntities{{/returnPassthrough}}} from "../runtimeSagasAndRecords{{importFileExtension}}"; +import {getApiEntitiesState} from "../ApiEntitiesSelectors{{importFileExtension}}" +import {List, Record, RecordOf, Map} from 'immutable'; +import {Schema, schema, NormalizedSchema} from "normalizr"; +import {select, call} from "redux-saga/effects"; + +import { + {{classname}}, +{{#vars}} +{{#isEnum}} + {{classname}}{{enumName}}, +{{/isEnum}} +{{/vars}} +} from './{{classname}}{{importFileExtension}}'; + +{{#imports}} +import { + {{{.}}}, +} from './{{{.}}}{{importFileExtension}}'; +{{/imports}} + +{{#modelImports}} +import { + {{{.}}}Record, + {{#lambda.camelcase}}{{.}}{{/lambda.camelcase}}RecordUtils +} from './{{{.}}}Record{{importFileExtension}}'; +{{/modelImports}} + +export const {{classname}}RecordProps = { + recType: "{{classname}}ApiRecord" as "{{classname}}ApiRecord", +{{#vars}} + {{#isArray}} + {{#items.isModel}} + {{#keepAsJSObject}} + {{name}}: {{#required}}new {{{dataType}}}(){{/required}}{{^required}}null as {{{dataType}}} | null{{/required}}, + {{/keepAsJSObject}} + {{^keepAsJSObject}} + {{name}}: ({{{items.dataType}}}Record(), {{#required}}{{{defaultValue}}}{{/required}}{{^required}}null as {{{dataTypeAlternate}}} | null{{/required}}), + {{/keepAsJSObject}} + {{/items.isModel}} + {{^items.isModel}} + {{name}}: {{#required}}{{{defaultValue}}}{{/required}}{{^required}}null as {{{dataTypeAlternate}}} | null{{/required}}, + {{/items.isModel}} + {{/isArray}} + {{#isModel}} + {{#keepAsJSObject}} + {{name}}: {{#required}}{} as any as {{{dataType}}}{{/required}}{{^required}}null as {{{dataType}}} | null{{/required}}, + {{/keepAsJSObject}} + {{^keepAsJSObject}} + {{name}}: {{#required}}{{{defaultValue}}}{{/required}}{{^required}}({{{defaultValue}}}, null as {{{dataTypeAlternate}}} | null){{/required}}, + {{/keepAsJSObject}} + {{/isModel}} + {{^isArray}} + {{^isModel}} + {{name}}: {{#required}}{{{defaultValue}}}{{/required}}{{^required}}null as {{{dataTypeAlternate}}} | null{{/required}}, + {{/isModel}} + {{/isArray}} +{{/vars}} +}; + +export type {{classname}}RecordPropsType = typeof {{classname}}RecordProps; +export const {{classname}}Record = Record({{classname}}RecordProps, {{classname}}RecordProps.recType); +export type {{classname}}Record = RecordOf<{{classname}}RecordPropsType>; + +knownRecordFactories.set({{classname}}RecordProps.recType, {{classname}}Record); + +{{#isEntity}} +export const {{classname}}RecordEntityProps = { + ...{{classname}}RecordProps, + recType: "{{classname}}ApiRecordEntity" as "{{classname}}ApiRecordEntity", +{{#vars}} + {{#isEntity}} + {{^keepAsJSObject}} + {{name}}: {{#required}}"-1"{{/required}}{{^required}}null as string | null{{/required}}, + {{/keepAsJSObject}} + {{/isEntity}} + {{#isArray}} + {{#items.isEntity}} + {{^keepAsJSObject}} + {{name}}: {{#required}}List(){{/required}}{{^required}}null as List | null{{/required}}, + {{/keepAsJSObject}} + {{/items.isEntity}} + {{/isArray}} +{{/vars}} +}; + +export type {{classname}}RecordEntityPropsType = typeof {{classname}}RecordEntityProps; +export const {{classname}}RecordEntity = Record({{classname}}RecordEntityProps, {{classname}}RecordEntityProps.recType); +export type {{classname}}RecordEntity = RecordOf<{{classname}}RecordEntityPropsType>; + +knownRecordFactories.set({{classname}}RecordEntityProps.recType, {{classname}}RecordEntity); +{{/isEntity}} + +class {{classname}}RecordUtils extends ApiRecordUtils<{{classname}}, {{classname}}Record> { + public normalize(apiObject: {{classname}}, asEntity?: boolean): {{classname}} { + (apiObject as any).recType = {{#isEntity}}asEntity ? {{classname}}RecordEntityProps.recType : {{/isEntity}}{{classname}}RecordProps.recType; +{{#vars}} + {{#isUniqueId}} + {{#isArray}} + {{#items.isArray}} + {{^required}}if (apiObject['{{name}}']) { {{/required}}(apiObject as any)['{{name}}'] = apiObject['{{name}}'].map(item => item.map(item2 => item2?.toString()));{{^required}} } {{/required}} + {{/items.isArray}} + {{^items.isArray}} + {{^required}}if (apiObject['{{name}}']) { {{/required}}(apiObject as any)['{{name}}'] = apiObject['{{name}}'].map(item => item?.toString());{{^required}} } {{/required}} + {{/items.isArray}} + {{/isArray}} + {{^isArray}} + {{^required}}if (apiObject['{{name}}']) { {{/required}}(apiObject as any)['{{name}}'] = apiObject['{{name}}'].toString();{{^required}} } {{/required}} + {{/isArray}} + {{/isUniqueId}} + {{^keepAsJSObject}} + {{#isModel}} + {{^required}}if (apiObject['{{name}}']) { {{/required}}{{#lambda.camelcase}}{{{dataTypeAlternate}}}{{/lambda.camelcase}}Utils.normalize(apiObject['{{name}}']);{{^required}} } {{/required}} + {{/isModel}} + {{#isArray}} + {{#items.isModel}} + {{^required}}if (apiObject['{{name}}']) { {{/required}}{{#lambda.camelcase}}{{items.dataType}}{{/lambda.camelcase}}RecordUtils.normalizeArray(apiObject['{{name}}']);{{^required}} } {{/required}} + {{/items.isModel}} + {{/isArray}} + {{/keepAsJSObject}} +{{/vars}} + return apiObject; + } +{{#isEntity}} + + public getSchema(): Schema { + return new schema.Entity("{{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}", { +{{#vars}} + {{#isEntity}} + {{^keepAsJSObject}} + {{name}}: {{#lambda.camelcase}}{{{dataTypeAlternate}}}{{/lambda.camelcase}}Utils.getSchema(), + {{/keepAsJSObject}} + {{/isEntity}} + {{#isArray}} + {{#items.isEntity}} + {{^keepAsJSObject}} + {{name}}: [{{#lambda.camelcase}}{{items.dataType}}{{/lambda.camelcase}}RecordUtils.getSchema()], + {{/keepAsJSObject}} + {{/items.isEntity}} + {{/isArray}} +{{/vars}} + }); + } + + public *toInlined(entityId?: string | null) { + if (!entityId) {return undefined; } + // @ts-ignore + const entity = yield select(apiEntity{{classname}}Selector, {id: entityId}); + if (!entity) {return undefined; } + + const { + recType, +{{#vars}} +{{#isEntity}} +{{^keepAsJSObject}} + {{name}}: {{name}}_original, +{{/keepAsJSObject}} +{{/isEntity}} +{{#isArray}} +{{#items.isEntity}} +{{^keepAsJSObject}} + {{name}}: {{name}}_original, +{{/keepAsJSObject}} +{{/items.isEntity}} +{{/isArray}} +{{/vars}} + ...unchangedProperties + } = entity; + + const entityProperties = { +{{#vars}} +{{#isEntity}} +{{^keepAsJSObject}} + // @ts-ignore + {{name}}: {{^required}}entity['{{name}}'] ? {{/required}}yield call({{#lambda.camelcase}}{{{dataTypeAlternate}}}{{/lambda.camelcase}}Utils.toInlined, entity['{{name}}']){{^required}} : null{{/required}}, +{{/keepAsJSObject}} +{{/isEntity}} +{{#isArray}} +{{#items.isEntity}} +{{^keepAsJSObject}} + // @ts-ignore + {{name}}: {{^required}}entity['{{name}}'] ? {{/required}}yield call({{#lambda.camelcase}}{{items.dataType}}{{/lambda.camelcase}}RecordUtils.toInlinedArray, entity['{{name}}']){{^required}} : null{{/required}}, +{{/keepAsJSObject}} +{{/items.isEntity}} +{{/isArray}} +{{/vars}} + } + + return {{classname}}Record({ + ...unchangedProperties, + ...entityProperties + }); +} + + public *toInlinedArray(entityIds: List | null) { + if (!entityIds) {return null; } + let entities = List<{{classname}}Record>(); + for (let entityIndex = 0; entityIndex < entityIds.count(); entityIndex++) { + // @ts-ignore + const entity = yield call(this.toInlined, entityIds.get(entityIndex)); + if (entity) { + entities.push(entity); + } + } + return entities; + } +{{/isEntity}} + + public toApi(record: {{classname}}Record): {{classname}} { + const apiObject = super.toApi(record); +{{#vars}} + {{#isUniqueId}} + {{#isArray}} + {{#items.isArray}} + {{^required}}if (record['{{name}}']) { {{/required}}apiObject['{{name}}'] = {{#isArray}}record['{{name}}'].map(item => item.toArray().map(item2 => (item2 ? parseFloat(item2) : null) as number)).toArray(){{/isArray}};{{^required}} } {{/required}} + {{/items.isArray}} + {{^items.isArray}} + {{^required}}if (record['{{name}}']) { {{/required}}apiObject['{{name}}'] = {{#isArray}}record['{{name}}'].map(item => (item ? parseFloat(item) : null) as number).toArray(){{/isArray}};{{^required}} } {{/required}} + {{/items.isArray}} + {{/isArray}} + {{^isArray}} + {{^required}}if (record['{{name}}']) { {{/required}}apiObject['{{name}}'] = {{^isArray}}parseFloat(record['{{name}}']){{/isArray}};{{^required}} } {{/required}} + {{/isArray}} + {{/isUniqueId}} + {{^keepAsJSObject}} + {{#isModel}} + {{^required}}if (record['{{name}}']) { {{/required}}apiObject['{{name}}'] = {{#lambda.camelcase}}{{{dataTypeAlternate}}}{{/lambda.camelcase}}Utils.toApi(record['{{name}}']);{{^required}} } {{/required}} + {{/isModel}} + {{#isArray}} + {{#items.isModel}} + {{^required}}if (record['{{name}}']) { {{/required}}apiObject['{{name}}'] = {{#lambda.camelcase}}{{items.dataType}}{{/lambda.camelcase}}RecordUtils.toApiArray(record['{{name}}']);{{^required}} } {{/required}} + {{/items.isModel}} + {{/isArray}} + {{/keepAsJSObject}} +{{/vars}} + return apiObject; + } +{{#returnPassthrough}} +{{#vars.1}} + + public fromApiPassthrough(apiObject: {{classname}}): {{{dataTypeAlternate}}} { + {{#isModel}} + if (!apiObject.{{{returnPassthrough}}}) {return {{{defaultValue}}}; } + const normalizedApiObject = {{#lambda.camelcase}}{{{dataTypeAlternate}}}{{/lambda.camelcase}}Utils.normalize(apiObject.{{{returnPassthrough}}}); + return appFromJS(normalizedApiObject); + {{/isModel}} + {{#isArray}} + {{#items.isModel}} + if (!apiObject.{{{returnPassthrough}}}) {return {{{defaultValue}}}; } + const normalizedApiObject = {{#lambda.camelcase}}{{items.dataType}}{{/lambda.camelcase}}RecordUtils.normalizeArray(apiObject.{{{returnPassthrough}}}); + return appFromJS(normalizedApiObject); + {{/items.isModel}} + {{^items.isModel}} + return appFromJS(apiObject.{{{returnPassthrough}}}); + {{/items.isModel}} + {{/isArray}} + {{^isModel}} + {{^isArray}} + return apiObject.{{{returnPassthrough}}}!; + {{/isArray}} + {{/isModel}} + } + + public fromApiPassthroughAsEntities(apiObject: {{classname}}): NormalizedRecordEntities { + {{#isEntity}} + if (!apiObject.{{{returnPassthrough}}}) {return {entities: {}, result: List()}; } + return ApiRecordUtils.toNormalizedRecordEntities({{#lambda.camelcase}}{{{dataTypeAlternate}}}{{/lambda.camelcase}}Utils.normalizeArrayAsEntities([apiObject.{{{returnPassthrough}}}]), true); + {{/isEntity}} + {{#isArray}} + {{#items.isEntity}} + if (!apiObject.{{{returnPassthrough}}}) {return {entities: {}, result: List()}; } + return ApiRecordUtils.toNormalizedRecordEntities({{#lambda.camelcase}}{{items.dataType}}{{/lambda.camelcase}}RecordUtils.normalizeArrayAsEntities(apiObject.{{{returnPassthrough}}}), true); + {{/items.isEntity}} + {{^items.isEntity}} + console.log("entities revival not supported on this response"); + return {entities: {}, result: List()}; + {{/items.isEntity}} + {{/isArray}} + {{^isEntity}} + {{^isArray}} + console.log("entities revival not supported on this response"); + return {entities: {}, result: List()}; + {{/isArray}} + {{/isEntity}} + } +{{/vars.1}} +{{/returnPassthrough}} +} + +export const {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}RecordUtils = new {{classname}}RecordUtils(); + +{{#isEntity}} +export const apiEntities{{classname}}Selector = (state: any) => getApiEntitiesState(state).{{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}} as Map; +export const apiEntity{{classname}}Selector = (state: any, {id}: {id?: string | null}) => id ? apiEntities{{classname}}Selector(state).get(id) : undefined; +{{/isEntity}} diff --git a/templates/node/records.mustache b/templates/node/records.mustache new file mode 100644 index 0000000..5c8a0ad --- /dev/null +++ b/templates/node/records.mustache @@ -0,0 +1,15 @@ +{{#models}} +{{#model}} +{{#isEnum}} +// This file is not needed and was generated only because of how codegen is built... Enums do not need to be converted to Records and can be used directly. +{{/isEnum}} +{{^isEnum}} +{{^oneOf}} +/* tslint:disable */ +/* eslint-disable */ +{{>licenseInfo}} +{{>recordGeneric}} +{{/oneOf}} +{{/isEnum}} +{{/model}} +{{/models}} diff --git a/templates/node/runtime.mustache b/templates/node/runtime.mustache new file mode 100644 index 0000000..19076a2 --- /dev/null +++ b/templates/node/runtime.mustache @@ -0,0 +1,419 @@ +/* tslint:disable */ +/* eslint-disable */ +{{>licenseInfo}} + +export const BASE_PATH = "{{{basePath}}}".replace(/\/+$/, ""); + +export interface ConfigurationParameters { + basePath?: string; // override base path + fetchApi?: FetchAPI; // override for fetch implementation + middleware?: Middleware[]; // middleware to apply before/after fetch requests + queryParamsStringify?: (params: HTTPQuery) => string; // stringify function for query strings + username?: string; // parameter for basic security + password?: string; // parameter for basic security + apiKey?: string | Promise | ((name: string) => string | Promise); // parameter for apiKey security + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string | Promise); // parameter for oauth2 security + headers?: HTTPHeaders; //header params we want to use on every request + credentials?: RequestCredentials; //value for the credentials param we want to use on each request +} + +export class Configuration { + constructor(private configuration: ConfigurationParameters = {}) {} + + set config(configuration: Configuration) { + this.configuration = configuration; + } + + get basePath(): string { + return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH; + } + + get fetchApi(): FetchAPI | undefined { + return this.configuration.fetchApi; + } + + get middleware(): Middleware[] { + return this.configuration.middleware || []; + } + + get queryParamsStringify(): (params: HTTPQuery) => string { + return this.configuration.queryParamsStringify || querystring; + } + + get username(): string | undefined { + return this.configuration.username; + } + + get password(): string | undefined { + return this.configuration.password; + } + + get apiKey(): ((name: string) => string | Promise) | undefined { + const apiKey = this.configuration.apiKey; + if (apiKey) { + return typeof apiKey === 'function' ? apiKey : () => apiKey; + } + return undefined; + } + + get accessToken(): ((name?: string, scopes?: string[]) => string | Promise) | undefined { + const accessToken = this.configuration.accessToken; + if (accessToken) { + return typeof accessToken === 'function' ? accessToken : async () => accessToken; + } + return undefined; + } + + get headers(): HTTPHeaders | undefined { + return this.configuration.headers; + } + + get credentials(): RequestCredentials | undefined { + return this.configuration.credentials; + } +} + +const DefaultConfigApi = new Configuration(); + +/** + * This is the base class for all generated API classes. + */ +export class BaseAPI { + + private static readonly jsonRegex = new RegExp('^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$', 'i'); + private middleware: Middleware[]; + + constructor(protected configuration = DefaultConfigApi) { + this.middleware = configuration.middleware; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime - MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + protected isJsonMime(mime: string | null | undefined): boolean { + if (!mime) { + return false; + } + return BaseAPI.jsonRegex.test(mime); + } + + protected async request(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction): Promise { + const { url, init } = await this.createFetchParams(context, initOverrides); + const response = await this.fetchApi(url, init); + if (response && (response.status >= 200 && response.status < 300)) { + return response; + } + let errorMessage = `HTTP ${response?.status} ${response?.statusText || 'Error'}`; + if (response) { + const responseClone = response.clone(); + try { + const responseBody = await responseClone.text(); + if (responseBody) { + errorMessage += ` – ${responseBody}`; + } + } catch { + // ignore body parse failures + } + } + throw new ResponseError(response, errorMessage); + } + + private async createFetchParams(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction) { + let url = this.configuration.basePath + context.path; + if (context.query !== undefined && Object.keys(context.query).length !== 0) { + // only add the querystring to the URL if there are query parameters. + // this is done to avoid urls ending with a "?" character which buggy webservers + // do not handle correctly sometimes. + url += '?' + this.configuration.queryParamsStringify(context.query); + } + + const headers = Object.assign({}, this.configuration.headers, context.headers); + Object.keys(headers).forEach(key => headers[key] === undefined ? delete headers[key] : {}); + + const initOverrideFn = + typeof initOverrides === "function" + ? initOverrides + : async () => initOverrides; + + const initParams = { + method: context.method, + headers, + body: context.body, + credentials: this.configuration.credentials, + }; + + const overriddenInit: RequestInit = { + ...initParams, + ...(await initOverrideFn({ + init: initParams, + context, + })) + }; + + let body: any; + if (isFormData(overriddenInit.body) + || (overriddenInit.body instanceof URLSearchParams) + || isBlob(overriddenInit.body)) { + body = overriddenInit.body; + } else if (this.isJsonMime(headers['Content-Type'])) { + body = JSON.stringify(overriddenInit.body); + } else { + body = overriddenInit.body; + } + + const init: RequestInit = { + ...overriddenInit, + body + }; + + return { url, init }; + } + + private fetchApi = async (url: string, init: RequestInit) => { + let fetchParams = { url, init }; + for (const middleware of this.middleware) { + if (middleware.pre) { + fetchParams = await middleware.pre({ + fetch: this.fetchApi, + ...fetchParams, + }) || fetchParams; + } + } + let response: Response | undefined = undefined; + try { + response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init); + } catch (e) { + for (const middleware of this.middleware) { + if (middleware.onError) { + response = await middleware.onError({ + fetch: this.fetchApi, + url: fetchParams.url, + init: fetchParams.init, + error: e, + response: response ? response.clone() : undefined, + }) || response; + } + } + if (response === undefined) { + if (e instanceof Error) { + throw new FetchError(e, 'The request failed and the interceptors did not return an alternative response'); + } else { + throw e; + } + } + } + for (const middleware of this.middleware) { + if (middleware.post) { + response = await middleware.post({ + fetch: this.fetchApi, + url: fetchParams.url, + init: fetchParams.init, + response: response.clone(), + }) || response; + } + } + return response; + } + + /** + * Create a shallow clone of `this` by constructing a new instance + * and then shallow cloning data members. + */ + private clone(this: T): T { + const constructor = this.constructor as any; + const next = new constructor(this.configuration); + next.middleware = this.middleware.slice(); + return next; + } +}; + +function isBlob(value: any): value is Blob { + return typeof Blob !== 'undefined' && value instanceof Blob; +} + +function isFormData(value: any): value is FormData { + return typeof FormData !== "undefined" && value instanceof FormData; +} + +export class ResponseError extends Error { + override name: "ResponseError" = "ResponseError"; + constructor(public response: Response, msg?: string) { + super(msg); + } +} + +export class FetchError extends Error { + override name: "FetchError" = "FetchError"; + constructor(public cause: Error, msg?: string) { + super(msg); + } +} + +export class RequiredError extends Error { + override name: "RequiredError" = "RequiredError"; + constructor(public field: string, msg?: string) { + super(msg); + } +} + +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +export type FetchAPI = WindowOrWorkerGlobalScope['fetch']; + +export type Json = any; +export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD'; +export type HTTPHeaders = { [key: string]: string }; +export type HTTPQuery = { [key: string]: string | number | null | boolean | Array | Set | HTTPQuery }; +export type HTTPBody = Json | FormData | URLSearchParams; +export type HTTPRequestInit = { headers?: HTTPHeaders; method: HTTPMethod; credentials?: RequestCredentials; body?: HTTPBody }; +export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original'; + +export type InitOverrideFunction = (requestContext: { init: HTTPRequestInit, context: RequestOpts }) => Promise + +export interface FetchParams { + url: string; + init: RequestInit; +} + +export interface RequestOpts { + path: string; + method: HTTPMethod; + headers: HTTPHeaders; + query?: HTTPQuery; + body?: HTTPBody; +} + +export function querystring(params: HTTPQuery, prefix: string = ''): string { + return Object.keys(params) + .map(key => querystringSingleKey(key, params[key], prefix)) + .filter(part => part.length > 0) + .join('&'); +} + +function querystringSingleKey(key: string, value: string | number | null | undefined | boolean | Array | Set | HTTPQuery, keyPrefix: string = ''): string { + const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key); + if (value instanceof Array) { + const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue))) + .join(`&${encodeURIComponent(fullKey)}=`); + return `${encodeURIComponent(fullKey)}=${multiValue}`; +} + if (value instanceof Set) { + const valueAsArray = Array.from(value); + return querystringSingleKey(key, valueAsArray, keyPrefix); + } + if (value instanceof Date) { + return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`; + } + if (value instanceof Object) { + return querystring(value as HTTPQuery, fullKey); + } + return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`; +} + +export function exists(json: any, key: string) { + const value = json[key]; + return value !== null && value !== undefined; +} + +{{^withoutRuntimeChecks}} +export function mapValues(data: any, fn: (item: any) => any) { + const result: { [key: string]: any } = {}; + for (const key of Object.keys(data)) { + result[key] = fn(data[key]); + } + return result; +} +{{/withoutRuntimeChecks}} + +export function canConsumeForm(consumes: Consume[]): boolean { + for (const consume of consumes) { + if ('multipart/form-data' === consume.contentType) { + return true; + } + } + return false; +} + +export interface Consume { + contentType: string; +} + +export interface RequestContext { + fetch: FetchAPI; + url: string; + init: RequestInit; +} + +export interface ResponseContext { + fetch: FetchAPI; + url: string; + init: RequestInit; + response: Response; +} + +export interface ErrorContext { + fetch: FetchAPI; + url: string; + init: RequestInit; + error: unknown; + response?: Response; +} + +export interface Middleware { + pre?(context: RequestContext): Promise; + post?(context: ResponseContext): Promise; + onError?(context: ErrorContext): Promise; +} + +export interface ApiResponse { + raw: Response; + value(): Promise; +} + +export interface ResponseTransformer { + (json: any): T; +} + +export class JSONApiResponse { + constructor(public raw: Response, private transformer: ResponseTransformer = (jsonValue: any) => jsonValue) {} + + async value(): Promise { + return this.transformer(await this.raw.json()); + } +} + +export class VoidApiResponse { + constructor(public raw: Response) {} + + async value(): Promise { + return undefined; + } +} + +export class BlobApiResponse { + constructor(public raw: Response) {} + + async value(): Promise { + return await this.raw.blob(); + }; +} + +export class TextApiResponse { + constructor(public raw: Response) {} + + async value(): Promise { + return await this.raw.text(); + }; +} diff --git a/templates/node/runtimeSagasAndRecords.mustache b/templates/node/runtimeSagasAndRecords.mustache new file mode 100644 index 0000000..80e0fcb --- /dev/null +++ b/templates/node/runtimeSagasAndRecords.mustache @@ -0,0 +1,120 @@ +/* tslint:disable */ +/* eslint-disable */ + +import {fromJS as originalFromJS, isIndexed, List, Map as ImmMap, RecordOf} from 'immutable'; +import {normalize, NormalizedSchema, schema, Schema} from "normalizr"; +import {ActionDefinition, createAction} from "redux-ts-simple"; + +export const knownRecordFactories = new Map(); +export const knownIndexedSetByKey: (string | number)[] = []; + +export function appFromJS(any: any): any { + return originalFromJS(any, (key, value) => { + if (isIndexed(value)) { + return knownIndexedSetByKey.indexOf(key) !== -1 ? value.toSet() : value.toList(); + } // we're reviving an array -> it's a List + const MatchingType = knownRecordFactories.get(value.get('recType') as string) as { new(input?: any): any }; // check if we know a Record with this type + if (MatchingType) { + return new MatchingType(value); + } + return value.toMap(); // no matching Record type found -> it's a plain old Map + }); +} + +export type NormalizedRecordEntity = NormalizedSchema<{ [key: string]: Map> }, string>; +export type NormalizedRecordEntities = NormalizedSchema<{ [key: string]: Map> }, List>; + +export abstract class ApiRecordUtils> { + public abstract normalize(apiObject: TAPI, asEntity?: boolean): any; + + public getSchema(): Schema { + console.log("Entity mode not supported on this record."); + return new schema.Entity("entityNotSupported"); + } + + public normalizeArray(apiObjectArray: TAPI[], asEntity?: boolean): TAPI[] { + apiObjectArray.forEach(apiObject => this.normalize(apiObject, asEntity)); + return apiObjectArray; + } + + public normalizeAsEntities(apiObject: TAPI): NormalizedSchema { + const normalized = this.normalize(apiObject, true); + return normalize(normalized, this.getSchema()); + } + + public normalizeArrayAsEntities(apiObject: TAPI[]): NormalizedSchema { + const normalized = this.normalizeArray(apiObject, true); + return normalize(normalized, new schema.Array(this.getSchema())); + } + + public fromApi(apiObject: TAPI): TREC { + return appFromJS(this.normalize(apiObject)); + } + + public fromApiArray(apiObjectArray: TAPI[]): List { + this.normalizeArray(apiObjectArray); + return appFromJS(apiObjectArray); + } + + public fromApiAsEntities(apiObject: TAPI): NormalizedRecordEntity { + return ApiRecordUtils.toNormalizedRecordEntities(this.normalizeAsEntities(apiObject), false); + } + + public fromApiArrayAsEntities(apiObject: TAPI[]): NormalizedRecordEntities { + return ApiRecordUtils.toNormalizedRecordEntities(this.normalizeArrayAsEntities(apiObject), true); + } + + public toApi(record: TREC): TAPI { + const apiObject = record.toJS(); + delete apiObject.recType; + return apiObject; + } + + public toApiArray(records: List): TAPI[] { + return records.map(record => this.toApi(record)).toArray(); + } + + public static toNormalizedRecordEntities(normalizedAsEntities: any, forArray: boolean) { + const entities = normalizedAsEntities.entities; + for (const entityKey of Object.keys(entities)) { + entities[entityKey] = appFromJS(entities[entityKey]); + } + normalizedAsEntities.result = appFromJS(normalizedAsEntities.result || (forArray ? "" : [])); + return normalizedAsEntities; + } +} + +export const allApiActionFailures: SagaActionDefinition[] = []; + +export interface BaseEntitySupportPayloadApiAction { + toInlined?: boolean; + toEntities?: boolean; + markErrorsAsHandled?: boolean; +} + +export interface BasePayloadApiAction { + markErrorsAsHandled?: boolean; +} + +export interface SagaActionDefinition extends ActionDefinition { + toString: () => string; +} + +export function createSagaAction(type: string, options?: { doNotAutoRegisterFailure?: boolean, namespace?: string }): SagaActionDefinition { + const {doNotAutoRegisterFailure, namespace} = options || {} as any; + let actionDefinition = createAction(namespace ? `${namespace}-${type}` : type); + (actionDefinition as any).toString = () => actionDefinition.type; + if (type.endsWith("Failure") && !doNotAutoRegisterFailure) { + allApiActionFailures.push(actionDefinition); + } + return actionDefinition; +} + +export let apiCall: any>(context: Ctx, fn: Fn, ...args: Parameters) => Generator; + +export function setApiCall(apiCallFc: any>(context: Ctx, fn: Fn, ...args: Parameters) => Generator) { + console.log("init apiCall"); + apiCall = apiCallFc; +} + +export const normalizedEntities = createSagaAction("normalizedEntities"); \ No newline at end of file diff --git a/templates/node/sagaApiManager.mustache b/templates/node/sagaApiManager.mustache new file mode 100644 index 0000000..69ebdfa --- /dev/null +++ b/templates/node/sagaApiManager.mustache @@ -0,0 +1,28 @@ +import { + Configuration, + ConfigurationParameters, +} from "../index{{importFileExtension}}"; + +import { +{{#apiInfo}} +{{#apis}} + {{classFilename}}, +{{/apis}} +{{/apiInfo}} +} from "./index{{importFileExtension}}"; + +export class Api { +{{#apiInfo}} +{{#apis}} + public static {{#lambda.camelcase}}{{classFilename}}{{/lambda.camelcase}}: {{classFilename}}; +{{/apis}} +{{/apiInfo}} + + public static init(apiBaseConfig: ConfigurationParameters) { +{{#apiInfo}} +{{#apis}} + Api.{{#lambda.camelcase}}{{classFilename}}{{/lambda.camelcase}} = new {{classFilename}}(new Configuration(apiBaseConfig)); +{{/apis}} +{{/apiInfo}} + } +} diff --git a/templates/node/sagas.mustache b/templates/node/sagas.mustache new file mode 100644 index 0000000..5127b2e --- /dev/null +++ b/templates/node/sagas.mustache @@ -0,0 +1,244 @@ +/* tslint:disable */ +/* eslint-disable */ +{{>licenseInfo}} + +import {Api} from './index{{importFileExtension}}'; +import {List} from 'immutable'; +import {all, fork, put, takeLatest} from "redux-saga/effects"; +import {apiCall, createSagaAction as originalCreateSagaAction, BaseEntitySupportPayloadApiAction, BasePayloadApiAction, NormalizedRecordEntities, normalizedEntities} from "../runtimeSagasAndRecords{{importFileExtension}}"; +import {Action} from "redux-ts-simple"; + +{{#imports.0}} +import { + {{#imports}} + {{className}}, + {{className}}Record, + {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}RecordUtils, + {{/imports}} + {{#passthroughImports}} + {{.}}, + {{/passthroughImports}} +} from '../model/index{{importFileExtension}}'; +{{/imports.0}} +{{#hasEnums}} +{{#operations}} +{{#operation}} +{{#allParams}} +{{#isEnum}} + +import { + {{operationIdCamelCase}}{{enumName}}, +} from './{{classname}}{{importFileExtension}}'; +{{/isEnum}} +{{/allParams}} +{{/operation}} +{{/operations}} +{{/hasEnums}} + +const createSagaAction = (type: string) => originalCreateSagaAction(type, {namespace: "api_{{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}"}); + +export const {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}SagaMap = new Map Generator>([ +{{#operations}} + {{#operation}} + ["{{nickname}}", {{nickname}}Saga], + {{/operation}} +{{/operations}} + ] +); + +export function *{{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}AllSagas() { + yield all([...{{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}SagaMap.values()].map(actionSaga => fork(actionSaga))); +} + +{{#operations}} +{{#operation}} +//region {{nickname}} + +{{#returnTypeSupportsEntities}} +export interface Payload{{#lambda.titlecase}}{{#lambda.camelcase}}{{nickname}}{{/lambda.camelcase}}{{/lambda.titlecase}} extends {{#allParams.0}}Payload{{#lambda.titlecase}}{{#lambda.camelcase}}{{nickname}}{{/lambda.camelcase}}{{/lambda.titlecase}}Request, {{/allParams.0}}BaseEntitySupportPayloadApiAction { +} +{{/returnTypeSupportsEntities}} +{{^returnTypeSupportsEntities}} +export interface Payload{{#lambda.titlecase}}{{#lambda.camelcase}}{{nickname}}{{/lambda.camelcase}}{{/lambda.titlecase}} extends {{#allParams.0}}Payload{{#lambda.titlecase}}{{#lambda.camelcase}}{{nickname}}{{/lambda.camelcase}}{{/lambda.titlecase}}Request, {{/allParams.0}}BasePayloadApiAction { +} +{{/returnTypeSupportsEntities}} + +{{#allParams.0}} +export interface Payload{{#lambda.titlecase}}{{#lambda.camelcase}}{{nickname}}{{/lambda.camelcase}}{{/lambda.titlecase}}Request { +{{#allParams}} + {{paramName}}{{^required}}?{{/required}}: {{{dataTypeAlternate}}}; +{{/allParams}} +} +{{/allParams.0}} + +export const {{nickname}}Request = createSagaAction<{{#allParams.0}}Payload{{#lambda.titlecase}}{{#lambda.camelcase}}{{nickname}}{{/lambda.camelcase}}{{/lambda.titlecase}}Request{{/allParams.0}}{{^allParams.0}}void{{/allParams.0}}>("{{nickname}}Request"); +{{#returnType}} +export const {{nickname}}Success = createSagaAction<{{#hasReturnPassthroughVoid}}void{{/hasReturnPassthroughVoid}}{{^hasReturnPassthroughVoid}}{{{returnTypeAlternate}}}{{/hasReturnPassthroughVoid}}>("{{nickname}}Success"); +{{#returnTypeSupportsEntities}} +export const {{nickname}}Success_Entities = createSagaAction("{{nickname}}Success_Entities"); +{{/returnTypeSupportsEntities}} +{{/returnType}} +{{^returnType}} +export const {{nickname}}Success = createSagaAction("{{nickname}}Success"); +{{/returnType}} +export const {{nickname}}Failure = createSagaAction<{error: any, requestPayload: Payload{{#lambda.titlecase}}{{#lambda.camelcase}}{{nickname}}{{/lambda.camelcase}}{{/lambda.titlecase}}}>("{{nickname}}Failure"); + +export const {{nickname}} = createSagaAction("{{nickname}}"); + +export function *{{nickname}}Saga() { + yield takeLatest({{nickname}}, {{nickname}}SagaImp); +} + +export function *{{nickname}}SagaImp(_action_: Action){{^returnType}}: any{{/returnType}} { + const {markErrorsAsHandled, ..._payloadRest_} = _action_.payload; + try { +{{#returnTypeSupportsEntities}} + const {toEntities, toInlined = !toEntities, ...requestPayload} = _payloadRest_; +{{/returnTypeSupportsEntities}} +{{#allParams.0}} + const { +{{#allParams}} + {{paramName}}, +{{/allParams}} + } = _payloadRest_; +{{/allParams.0}} + + yield put({{nickname}}Request({{#allParams.0}}{{#returnTypeSupportsEntities}}requestPayload{{/returnTypeSupportsEntities}}{{^returnTypeSupportsEntities}}_action_.payload{{/returnTypeSupportsEntities}}{{/allParams.0}})); + + const response{{#returnType}}: Required<{{{returnType}}}>{{/returnType}} = yield apiCall(Api.{{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}, Api.{{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}['{{nickname}}'], +{{#allParams.0}} +{{#allParams}} +{{#isUniqueId}} +{{#isArray}} +{{#items.isArray}} + {{^required}}{{paramName}} ? {{/required}}{{paramName}}.map(p => p.toArray().map(p2 => (p2 ? parseFloat(p2) : null) as number)).toArray(){{^required}} : undefined{{/required}}, +{{/items.isArray}} +{{^items.isArray}} + {{^required}}{{paramName}} ? {{/required}}{{paramName}}.map(p => (p ? parseFloat(p) : null) as number ).toArray(){{^required}} : undefined{{/required}}, +{{/items.isArray}} +{{/isArray}} +{{^isArray}} + {{^required}}{{paramName}} ? {{/required}}parseFloat({{paramName}}){{^required}} : undefined{{/required}}, +{{/isArray}} +{{/isUniqueId}} +{{^isUniqueId}} +{{#isArray}} +{{#items.isModel}} + {{^required}}{{paramName}} ? {{/required}}{{#lambda.camelcase}}{{items.dataType}}{{/lambda.camelcase}}RecordUtils.toApiArray({{paramName}}){{^required}} : undefined{{/required}}, +{{/items.isModel}} +{{^items.isModel}} + {{^required}}{{paramName}} ? {{/required}}{{paramName}}.toJS(){{^required}} : undefined{{/required}}, +{{/items.isModel}} +{{/isArray}} +{{#isModel}} + {{^required}}{{paramName}} ? {{/required}}{{#lambda.camelcase}}{{{dataTypeAlternate}}}{{/lambda.camelcase}}Utils.toApi({{paramName}}){{^required}} : undefined{{/required}}, +{{/isModel}} +{{^isArray}} +{{^isModel}} + {{paramName}}, +{{/isModel}} +{{/isArray}} +{{/isUniqueId}} +{{/allParams}} +{{/allParams.0}} + ); + +{{#returnType}} +{{^hasReturnPassthroughVoid}} + let successReturnValue: any = undefined; +{{/hasReturnPassthroughVoid}} +{{/returnType}} +{{#returnTypeSupportsEntities}} + if (toEntities) { +{{#returnPassthrough}} + successReturnValue = {{#lambda.camelcase}}{{{returnType}}}{{/lambda.camelcase}}RecordUtils.fromApiPassthroughAsEntities(response); +{{/returnPassthrough}} +{{^hasReturnPassthroughVoid}} +{{^returnPassthrough}} +{{#returnTypeIsArray}} +{{#returnTypeAlternate}} + successReturnValue = {{#lambda.camelcase}}{{returnBaseTypeAlternate}}{{/lambda.camelcase}}Utils.fromApiArrayAsEntities(response); +{{/returnTypeAlternate}} +{{/returnTypeIsArray}} +{{#returnTypeIsModel}} + successReturnValue = {{#lambda.camelcase}}{{returnTypeAlternate}}{{/lambda.camelcase}}Utils.fromApiArrayAsEntities([response]); +{{/returnTypeIsModel}} +{{/returnPassthrough}} +{{/hasReturnPassthroughVoid}} + yield put(normalizedEntities(successReturnValue)); + yield put({{nickname}}Success_Entities(successReturnValue)); + } + if (toInlined) { +{{/returnTypeSupportsEntities}} +{{#returnType}} +{{#returnPassthrough}} + successReturnValue = {{#lambda.camelcase}}{{{returnType}}}{{/lambda.camelcase}}RecordUtils.fromApiPassthrough(response); + yield put({{nickname}}Success(successReturnValue)); +{{/returnPassthrough}} +{{#hasReturnPassthroughVoid}} + yield put({{nickname}}Success()); +{{/hasReturnPassthroughVoid}} +{{^hasReturnPassthroughVoid}} +{{^returnPassthrough}} +{{#returnTypeIsArray}} +{{#returnTypeAlternate}} + successReturnValue = {{#lambda.camelcase}}{{returnBaseTypeAlternate}}{{/lambda.camelcase}}Utils.fromApiArray(response); + yield put({{nickname}}Success(successReturnValue)); +{{/returnTypeAlternate}} +{{/returnTypeIsArray}} +{{#returnTypeIsModel}} + successReturnValue = {{#lambda.camelcase}}{{returnTypeAlternate}}{{/lambda.camelcase}}Utils.fromApi(response); + yield put({{nickname}}Success(successReturnValue)); +{{/returnTypeIsModel}} +{{^returnTypeIsArray}} +{{^returnTypeIsModel}} + yield put({{nickname}}Success(response)); +{{/returnTypeIsModel}} +{{/returnTypeIsArray}} +{{/returnPassthrough}} +{{/hasReturnPassthroughVoid}} +{{/returnType}} +{{^returnType}} + yield put({{nickname}}Success()); +{{/returnType}} +{{#returnTypeSupportsEntities}} + } +{{/returnTypeSupportsEntities}} + +{{#returnType}} +{{#returnPassthrough}} + return successReturnValue; +{{/returnPassthrough}} +{{#hasReturnPassthroughVoid}} + return undefined; +{{/hasReturnPassthroughVoid}} +{{^hasReturnPassthroughVoid}} +{{^returnPassthrough}} +{{#returnTypeIsArray}} +{{#returnTypeAlternate}} + return successReturnValue; +{{/returnTypeAlternate}} +{{/returnTypeIsArray}} +{{#returnTypeIsModel}} + return successReturnValue; +{{/returnTypeIsModel}} +{{^returnTypeIsArray}} +{{^returnTypeIsModel}} + return response; +{{/returnTypeIsModel}} +{{/returnTypeIsArray}} +{{/returnPassthrough}} +{{/hasReturnPassthroughVoid}} +{{/returnType}} +{{^returnType}} + return undefined; +{{/returnType}} + } catch (error: any) { + if (markErrorsAsHandled) {error.wasHandled = true; } + yield put({{nickname}}Failure({error, requestPayload: _action_.payload})); + return error; + } +} +//endregion +{{/operation}} +{{/operations}} diff --git a/templates/node/sourceLibraryIndex.mustache b/templates/node/sourceLibraryIndex.mustache new file mode 100644 index 0000000..3a0629e --- /dev/null +++ b/templates/node/sourceLibraryIndex.mustache @@ -0,0 +1 @@ +export * from './src/index{{importFileExtension}}'; diff --git a/templates/node/tsconfig.esm.mustache b/templates/node/tsconfig.esm.mustache new file mode 100644 index 0000000..2c0331c --- /dev/null +++ b/templates/node/tsconfig.esm.mustache @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "esnext", + "outDir": "dist/esm" + } +} diff --git a/templates/node/tsconfig.mustache b/templates/node/tsconfig.mustache new file mode 100644 index 0000000..a8778b0 --- /dev/null +++ b/templates/node/tsconfig.mustache @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "declaration": true, + "target": "{{#supportsES6}}es6{{/supportsES6}}{{^supportsES6}}es5{{/supportsES6}}", +{{#sagasAndRecords}} + "strict": true, +{{/sagasAndRecords}} + "module": "commonjs", + "moduleResolution": "node", + "outDir": "dist", + {{^supportsES6}} + "lib": [ + "es6", + "dom" + ], + {{/supportsES6}} + "typeRoots": [ + "node_modules/@types" + ] + }, + "exclude": [ + "dist", + "node_modules" + ] +} diff --git a/tests/setup.ts b/tests/setup.ts index ee1024e..681e2bb 100644 --- a/tests/setup.ts +++ b/tests/setup.ts @@ -1,6 +1,6 @@ import nock from 'nock'; -import dotenv from "dotenv"; +import dotenv from 'dotenv'; dotenv.config(); diff --git a/tests/unit/core/oauth2-client.test.ts b/tests/unit/core/oauth2-client.test.ts index 6688a20..ce9ab79 100644 --- a/tests/unit/core/oauth2-client.test.ts +++ b/tests/unit/core/oauth2-client.test.ts @@ -17,32 +17,26 @@ describe('OAuth2Client', () => { access_token: 'access-token-123', token_type: 'Bearer', expires_in: 3600, - refresh_token: 'refresh-token-123' + refresh_token: 'refresh-token-123', }; - nock('https://auth.upsun.com') - .post('/oauth2/token') - .reply(200, mockTokenResponse); + nock('https://auth.upsun.com').post('/oauth2/token').reply(200, mockTokenResponse); const result = await oauth2Client.exchangeCodeForToken(); expect(typeof result).toBe('boolean'); }); it('should handle token exchange errors', async () => { - nock('https://auth.upsun.com') - .post('/oauth2/token') - .reply(400, { - error: 'invalid_grant', - error_description: 'Invalid authorization code' - }); + nock('https://auth.upsun.com').post('/oauth2/token').reply(400, { + error: 'invalid_grant', + error_description: 'Invalid authorization code', + }); await expect(oauth2Client.exchangeCodeForToken()).rejects.toThrow('Token exchange failed'); }); it('should handle network errors during token exchange', async () => { - nock('https://auth.upsun.com') - .post('/oauth2/token') - .replyWithError('Network error'); + nock('https://auth.upsun.com').post('/oauth2/token').replyWithError('Network error'); await expect(oauth2Client.exchangeCodeForToken()).rejects.toThrow('Network error'); }); @@ -51,16 +45,14 @@ describe('OAuth2Client', () => { describe('getAuthorization', () => { it('should return cached access token if valid', async () => { // First exchange to set token - nock('https://auth.upsun.com') - .post('/oauth2/token') - .reply(200, { - access_token: 'cached-token-123', - token_type: 'Bearer', - expires_in: 3600 - }); + nock('https://auth.upsun.com').post('/oauth2/token').reply(200, { + access_token: 'cached-token-123', + token_type: 'Bearer', + expires_in: 3600, + }); await oauth2Client.exchangeCodeForToken(); - + // Should return cached token without new request const token = await oauth2Client.getAuthorization(); expect(typeof token).toBe('string'); @@ -68,25 +60,21 @@ describe('OAuth2Client', () => { it('should refresh token if expired', async () => { // Mock initial token that expires quickly - nock('https://auth.upsun.com') - .post('/oauth2/token') - .reply(200, { - access_token: 'initial-token', - token_type: 'Bearer', - expires_in: -1, // Already expired - refresh_token: 'refresh-token' - }); + nock('https://auth.upsun.com').post('/oauth2/token').reply(200, { + access_token: 'initial-token', + token_type: 'Bearer', + expires_in: -1, // Already expired + refresh_token: 'refresh-token', + }); await oauth2Client.exchangeCodeForToken(); // Mock refresh token request - nock('https://auth.upsun.com') - .post('/oauth2/token') - .reply(200, { - access_token: 'refreshed-token', - token_type: 'Bearer', - expires_in: 3600 - }); + nock('https://auth.upsun.com').post('/oauth2/token').reply(200, { + access_token: 'refreshed-token', + token_type: 'Bearer', + expires_in: 3600, + }); const token = await oauth2Client.getAuthorization(); expect(typeof token).toBe('string'); @@ -94,23 +82,19 @@ describe('OAuth2Client', () => { it('should handle refresh token errors', async () => { // Mock expired token - nock('https://auth.upsun.com') - .post('/oauth2/token') - .reply(200, { - access_token: 'initial-token', - token_type: 'Bearer', - expires_in: -1, - refresh_token: 'invalid-refresh-token' - }); + nock('https://auth.upsun.com').post('/oauth2/token').reply(200, { + access_token: 'initial-token', + token_type: 'Bearer', + expires_in: -1, + refresh_token: 'invalid-refresh-token', + }); await oauth2Client.exchangeCodeForToken(); // Mock failed refresh - nock('https://auth.upsun.com') - .post('/oauth2/token') - .reply(400, { - error: 'invalid_grant' - }); + nock('https://auth.upsun.com').post('/oauth2/token').reply(400, { + error: 'invalid_grant', + }); await expect(oauth2Client.getAuthorization()).rejects.toThrow(); }); diff --git a/tests/unit/tasks/activity.test.ts b/tests/unit/tasks/activities.test.ts similarity index 63% rename from tests/unit/tasks/activity.test.ts rename to tests/unit/tasks/activities.test.ts index f8ff125..b51d540 100644 --- a/tests/unit/tasks/activity.test.ts +++ b/tests/unit/tasks/activities.test.ts @@ -1,13 +1,13 @@ -import { ActivityTask } from '../../../src/core/tasks/activity.js'; +import { ActivitiesTask } from '../../../src/core/tasks/activities.js'; import { UpsunClient } from '../../../src/upsun.js'; -import { ProjectActivityApi, EnvironmentActivityApi } from '../../../src/apis-gen/index.js'; +import { ProjectActivityApi, EnvironmentActivityApi } from '../../../src/api/index.js'; // Mock the UpsunClient and APIs jest.mock('../../../src/upsun.js'); -jest.mock('../../../src/apis-gen/index.js'); +jest.mock('../../../src/api/index.js'); -describe('ActivityTask', () => { - let activityTask: ActivityTask; +describe('ActivitiesTask', () => { + let activitiesTask: ActivitiesTask; let mockClient: jest.Mocked; let mockProjectActivityApi: jest.Mocked; let mockEnvironmentActivityApi: jest.Mocked; @@ -16,25 +16,33 @@ describe('ActivityTask', () => { mockProjectActivityApi = { listProjectsActivities: jest.fn(), getProjectsActivities: jest.fn(), - actionProjectsActivitiesCancel: jest.fn() + actionProjectsActivitiesCancel: jest.fn(), } as any; mockEnvironmentActivityApi = { listProjectsEnvironmentsActivities: jest.fn(), getProjectsEnvironmentsActivities: jest.fn(), - actionProjectsEnvironmentsActivitiesCancel: jest.fn() + actionProjectsEnvironmentsActivitiesCancel: jest.fn(), } as any; - (ProjectActivityApi as jest.MockedClass).mockImplementation(() => mockProjectActivityApi); - (EnvironmentActivityApi as jest.MockedClass).mockImplementation(() => mockEnvironmentActivityApi); + (ProjectActivityApi as jest.MockedClass).mockImplementation( + () => mockProjectActivityApi, + ); + (EnvironmentActivityApi as jest.MockedClass).mockImplementation( + () => mockEnvironmentActivityApi, + ); mockClient = { apiConfig: { - basePath: 'https://api.upsun.com' - } + basePath: 'https://api.upsun.com', + }, } as any; - - activityTask = new ActivityTask(mockClient); + + activitiesTask = new ActivitiesTask( + mockClient, + mockProjectActivityApi, + mockEnvironmentActivityApi, + ); }); afterEach(() => { @@ -43,8 +51,8 @@ describe('ActivityTask', () => { describe('list', () => { it('should have list method defined', () => { - expect(activityTask.list).toBeDefined(); - expect(typeof activityTask.list).toBe('function'); + expect(activitiesTask.list).toBeDefined(); + expect(typeof activitiesTask.list).toBe('function'); }); it('should list project activities', async () => { @@ -53,26 +61,26 @@ describe('ActivityTask', () => { id: 'activity-1', type: 'environment.backup', state: 'complete', - created_at: '2023-01-01T00:00:00Z' - } + created_at: '2023-01-01T00:00:00Z', + }, ]; mockProjectActivityApi.listProjectsActivities.mockResolvedValue(mockActivities as any); - const result = await activityTask.list('project-123'); + const result = await activitiesTask.list('project-123'); expect(result).toBeDefined(); expect(result).toHaveLength(1); expect((result[0] as any).id).toBe('activity-1'); expect(mockProjectActivityApi.listProjectsActivities).toHaveBeenCalledWith({ - projectId: 'project-123' + projectId: 'project-123', }); }); }); describe('get', () => { it('should have get method defined', () => { - expect(activityTask.get).toBeDefined(); - expect(typeof activityTask.get).toBe('function'); + expect(activitiesTask.get).toBeDefined(); + expect(typeof activitiesTask.get).toBe('function'); }); it('should get a specific activity', async () => { @@ -80,25 +88,25 @@ describe('ActivityTask', () => { id: 'activity-123', type: 'environment.backup', state: 'complete', - created_at: '2023-01-01T00:00:00Z' + created_at: '2023-01-01T00:00:00Z', }; mockProjectActivityApi.getProjectsActivities.mockResolvedValue(mockActivity as any); - const result = await activityTask.get('project-123', 'activity-123'); + const result = await activitiesTask.get('project-123', 'activity-123'); expect(result).toBeDefined(); expect((result as any).id).toBe('activity-123'); expect(mockProjectActivityApi.getProjectsActivities).toHaveBeenCalledWith({ projectId: 'project-123', - activityId: 'activity-123' + activityId: 'activity-123', }); }); }); describe('cancel', () => { it('should have cancel method defined', () => { - expect(activityTask.cancel).toBeDefined(); - expect(typeof activityTask.cancel).toBe('function'); + expect(activitiesTask.cancel).toBeDefined(); + expect(typeof activitiesTask.cancel).toBe('function'); }); it('should cancel an activity', async () => { @@ -106,18 +114,20 @@ describe('ActivityTask', () => { mockProjectActivityApi.actionProjectsActivitiesCancel.mockResolvedValue(mockResult as any); - const result = await activityTask.cancel('project-123', 'activity-123'); + const result = await activitiesTask.cancel('project-123', 'activity-123'); expect(result).toBeDefined(); expect(mockProjectActivityApi.actionProjectsActivitiesCancel).toHaveBeenCalledWith({ projectId: 'project-123', - activityId: 'activity-123' + activityId: 'activity-123', }); }); }); describe('log', () => { it('should throw not implemented error', async () => { - await expect(activityTask.log('project-123', 'activity-123')).rejects.toThrow('Not implemented'); + await expect(activitiesTask.log('project-123', 'activity-123')).rejects.toThrow( + 'Not implemented', + ); }); }); }); diff --git a/tests/unit/tasks/application.test.ts b/tests/unit/tasks/application.test.ts deleted file mode 100644 index fda354e..0000000 --- a/tests/unit/tasks/application.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { ApplicationTask } from '../../../src/core/tasks/application.js'; -import { UpsunClient } from '../../../src/upsun.js'; - -// Mock the UpsunClient -jest.mock('../../../src/upsun'); - -describe('ApplicationTask', () => { - let applicationTask: ApplicationTask; - let mockClient: jest.Mocked; - - beforeEach(() => { - mockClient = { - apiConfig: { - basePath: 'https://api.upsun.com' - } - } as any; - - applicationTask = new ApplicationTask(mockClient); - }); - - describe('constructor', () => { - it('should initialize properly', () => { - expect(applicationTask).toBeDefined(); - expect(applicationTask).toBeInstanceOf(ApplicationTask); - }); - }); - - // Note: ApplicationTask currently has no implemented methods - // Tests will be added when methods are implemented -}); diff --git a/tests/unit/tasks/applications.test.ts b/tests/unit/tasks/applications.test.ts new file mode 100644 index 0000000..a5d7c2e --- /dev/null +++ b/tests/unit/tasks/applications.test.ts @@ -0,0 +1,30 @@ +import { ApplicationsTask } from '../../../src/core/tasks/applications.js'; +import { UpsunClient } from '../../../src/upsun.js'; + +// Mock the UpsunClient +jest.mock('../../../src/upsun'); + +describe('ApplicationsTask', () => { + let applicationsTask: ApplicationsTask; + let mockClient: jest.Mocked; + + beforeEach(() => { + mockClient = { + apiConfig: { + basePath: 'https://api.upsun.com', + }, + } as any; + + applicationsTask = new ApplicationsTask(mockClient); + }); + + describe('constructor', () => { + it('should initialize properly', () => { + expect(applicationsTask).toBeDefined(); + expect(applicationsTask).toBeInstanceOf(ApplicationsTask); + }); + }); + + // Note: ApplicationsTask currently has no implemented methods + // Tests will be added when methods are implemented +}); diff --git a/tests/unit/tasks/backup.test.ts b/tests/unit/tasks/backup.test.ts deleted file mode 100644 index 65553eb..0000000 --- a/tests/unit/tasks/backup.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { BackupTask } from '../../../src/core/tasks/backup.js'; -import { UpsunClient } from '../../../src/upsun.js'; -import { EnvironmentBackupsApi } from '../../../src/apis-gen/index.js'; - -// Mock the UpsunClient and EnvironmentBackupsApi -jest.mock('../../../src/upsun'); -jest.mock('../../../src/apis-gen/index.js'); - -describe('BackupTask', () => { - let backupTask: BackupTask; - let mockClient: jest.Mocked; - let mockBackupsApi: jest.Mocked; - - beforeEach(() => { - mockBackupsApi = { - backupEnvironment: jest.fn(), - deleteProjectsEnvironmentsBackups: jest.fn(), - getProjectsEnvironmentsBackups: jest.fn(), - listProjectsEnvironmentsBackups: jest.fn(), - restoreEnvironmentBackup: jest.fn() - } as any; - - (EnvironmentBackupsApi as jest.MockedClass).mockImplementation(() => mockBackupsApi); - - mockClient = { - apiConfig: { - basePath: 'https://api.upsun.com' - } - } as any; - - backupTask = new BackupTask(mockClient); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('create', () => { - it('should have create method defined', () => { - expect(backupTask.create).toBeDefined(); - expect(typeof backupTask.create).toBe('function'); - }); - - it('should create a backup', async () => { - const mockActivity = { - id: 'activity-backup-123', - type: 'environment.backup' - }; - - mockBackupsApi.backupEnvironment.mockResolvedValue(mockActivity as any); - - const result = await backupTask.create('project-123', 'main'); - expect(result).toBeDefined(); - expect(mockBackupsApi.backupEnvironment).toHaveBeenCalledWith({ - projectId: 'project-123', - environmentId: 'main', - environmentBackupInput: { safe: true } - }); - }); - - it('should handle backup creation errors', async () => { - mockBackupsApi.backupEnvironment.mockRejectedValue(new Error('Backup creation failed')); - - await expect(backupTask.create('project-123', 'main')).rejects.toThrow('Backup creation failed'); - }); - }); - - describe('list', () => { - it('should have list method defined', () => { - expect(backupTask.list).toBeDefined(); - expect(typeof backupTask.list).toBe('function'); - }); - - it('should list environment backups', async () => { - const mockBackups = [ - { - id: 'backup-1', - createdAt: '2023-01-01T00:00:00Z', - status: 'complete', - }, - { - id: 'backup-2', - createdAt: '2023-01-02T00:00:00Z', - status: 'complete', - } - ]; - - mockBackupsApi.listProjectsEnvironmentsBackups.mockResolvedValue(mockBackups as any); - - const result = await backupTask.list('project-123', 'main'); - expect(result).toBeDefined(); - expect(result).toHaveLength(2); - expect(result[0].id).toBe('backup-1'); - expect(result[1].id).toBe('backup-2'); - expect(mockBackupsApi.listProjectsEnvironmentsBackups).toHaveBeenCalledWith({ - projectId: 'project-123', - environmentId: 'main' - }); - }); - - it('should handle empty backup list', async () => { - mockBackupsApi.listProjectsEnvironmentsBackups.mockResolvedValue([]); - - const result = await backupTask.list('project-123', 'main'); - expect(result).toEqual([]); - }); - }); - - describe('restore', () => { - it('should have restore method defined', () => { - expect(backupTask.restore).toBeDefined(); - expect(typeof backupTask.restore).toBe('function'); - }); - - it('should restore from backup', async () => { - await expect(backupTask.restore('project-123', 'main', 'backup-1')).rejects.toThrow('Not implemented'); - }); - it('should handle restore errors', async () => { - await expect(backupTask.restore('project-123', 'main', 'invalid-backup')).rejects.toThrow('Not implemented'); - }); - }); -}); -//# sourceMappingURL=backup.test.js.map diff --git a/tests/unit/tasks/backups.test.ts b/tests/unit/tasks/backups.test.ts new file mode 100644 index 0000000..c131f4a --- /dev/null +++ b/tests/unit/tasks/backups.test.ts @@ -0,0 +1,155 @@ +import { BackupsTask } from '../../../src/core/tasks/backups.js'; +import { UpsunClient } from '../../../src/upsun.js'; +import { EnvironmentBackupsApi } from '../../../src/api/index.js'; +import { Resources6InitEnum } from '../../../src/model/index.js'; + +// Mock the UpsunClient and EnvironmentBackupsApi +jest.mock('../../../src/upsun'); +jest.mock('../../../src/api/index.js'); + +describe('BackupsTask', () => { + let backupsTask: BackupsTask; + let mockClient: jest.Mocked; + let mockBackupsApi: jest.Mocked; + + beforeEach(() => { + mockBackupsApi = { + backupEnvironment: jest.fn(), + deleteProjectsEnvironmentsBackups: jest.fn(), + getProjectsEnvironmentsBackups: jest.fn(), + listProjectsEnvironmentsBackups: jest.fn(), + restoreBackup: jest.fn(), + } as any; + + (EnvironmentBackupsApi as jest.MockedClass).mockImplementation( + () => mockBackupsApi, + ); + + mockClient = { + apiConfig: { + basePath: 'https://api.upsun.com', + }, + } as any; + + backupsTask = new BackupsTask(mockClient, mockBackupsApi); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('create', () => { + it('should have create method defined', () => { + expect(backupsTask.create).toBeDefined(); + expect(typeof backupsTask.create).toBe('function'); + }); + + it('should create a backup', async () => { + const mockActivity = { + id: 'activity-backup-123', + type: 'environment.backup', + }; + + mockBackupsApi.backupEnvironment.mockResolvedValue(mockActivity as any); + + const result = await backupsTask.create('project-123', 'main'); + expect(result).toBeDefined(); + expect(mockBackupsApi.backupEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + environmentBackupInput: { safe: true }, + }); + }); + + it('should handle backup creation errors', async () => { + mockBackupsApi.backupEnvironment.mockRejectedValue(new Error('Backup creation failed')); + + await expect(backupsTask.create('project-123', 'main')).rejects.toThrow( + 'Backup creation failed', + ); + }); + }); + + describe('list', () => { + it('should have list method defined', () => { + expect(backupsTask.list).toBeDefined(); + expect(typeof backupsTask.list).toBe('function'); + }); + + it('should list environment backups', async () => { + const mockBackups = [ + { + id: 'backup-1', + createdAt: '2023-01-01T00:00:00Z', + status: 'complete', + }, + { + id: 'backup-2', + createdAt: '2023-01-02T00:00:00Z', + status: 'complete', + }, + ]; + + mockBackupsApi.listProjectsEnvironmentsBackups.mockResolvedValue(mockBackups as any); + + const result = await backupsTask.list('project-123', 'main'); + expect(result).toBeDefined(); + expect(result).toHaveLength(2); + expect(result[0].id).toBe('backup-1'); + expect(result[1].id).toBe('backup-2'); + expect(mockBackupsApi.listProjectsEnvironmentsBackups).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + }); + }); + + it('should handle empty backup list', async () => { + mockBackupsApi.listProjectsEnvironmentsBackups.mockResolvedValue([]); + + const result = await backupsTask.list('project-123', 'main'); + expect(result).toEqual([]); + }); + }); + + describe('restore', () => { + it('should have restore method defined', () => { + expect(backupsTask.restore).toBeDefined(); + expect(typeof backupsTask.restore).toBe('function'); + }); + + it('should restore from backup', async () => { + const mockActivity = { + id: 'activity-restore-123', + type: 'environment.restore', + }; + + mockBackupsApi.restoreBackup.mockResolvedValue(mockActivity as any); + + const result = await backupsTask.restore('project-123', 'main', 'backup-1'); + + expect(result).toBeDefined(); + expect(result).toEqual(mockActivity); + expect(mockBackupsApi.restoreBackup).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + backupId: 'backup-1', + environmentRestoreInput: { + environmentName: null, + branchFrom: null, + restoreCode: true, + restoreResources: true, + resources: { init: Resources6InitEnum.DEFAULT }, + }, + }); + }); + + it('should handle restore errors', async () => { + mockBackupsApi.restoreBackup.mockRejectedValue(new Error('Restore failed')); + + await expect(backupsTask.restore('project-123', 'main', 'backup-1')).rejects.toThrow( + 'Restore failed', + ); + }); + }); +}); +//# sourceMappingURL=backup.test.js.map diff --git a/tests/unit/tasks/certificate.test.ts b/tests/unit/tasks/certificates.test.ts similarity index 55% rename from tests/unit/tasks/certificate.test.ts rename to tests/unit/tasks/certificates.test.ts index 315ee4a..6248186 100644 --- a/tests/unit/tasks/certificate.test.ts +++ b/tests/unit/tasks/certificates.test.ts @@ -1,13 +1,13 @@ -import { CertificateTask } from '../../../src/core/tasks/certificate.js'; +import { CertificatesTask } from '../../../src/core/tasks/certificates.js'; import { UpsunClient } from '../../../src/upsun.js'; -import { CertManagementApi } from '../../../src/apis-gen/index.js'; +import { CertManagementApi } from '../../../src/api/index.js'; // Mock the UpsunClient and CertManagementApi jest.mock('../../../src/upsun'); -jest.mock('../../../src/apis-gen/index.js'); +jest.mock('../../../src/api/index.js'); -describe('CertificateTask', () => { - let certificateTask: CertificateTask; +describe('CertificatesTask', () => { + let certificatesTask: CertificatesTask; let mockClient: jest.Mocked; let mockCertApi: jest.Mocked; @@ -16,18 +16,21 @@ describe('CertificateTask', () => { createProjectsCertificates: jest.fn(), deleteProjectsCertificates: jest.fn(), getProjectsCertificates: jest.fn(), - listProjectsCertificates: jest.fn() + listProjectsCertificates: jest.fn(), + updateProjectsCertificates: jest.fn(), } as any; - (CertManagementApi as jest.MockedClass).mockImplementation(() => mockCertApi); + (CertManagementApi as jest.MockedClass).mockImplementation( + () => mockCertApi, + ); mockClient = { apiConfig: { - basePath: 'https://api.upsun.com' - } + basePath: 'https://api.upsun.com', + }, } as any; - - certificateTask = new CertificateTask(mockClient); + + certificatesTask = new CertificatesTask(mockClient, mockCertApi); }); afterEach(() => { @@ -36,31 +39,31 @@ describe('CertificateTask', () => { describe('add', () => { it('should have add method defined', () => { - expect(certificateTask.add).toBeDefined(); - expect(typeof certificateTask.add).toBe('function'); + expect(certificatesTask.add).toBeDefined(); + expect(typeof certificatesTask.add).toBe('function'); }); it('should add a certificate to project', async () => { const mockCertificate = { id: 'cert-123', certificate: '-----BEGIN CERTIFICATE-----', - created_at: '2023-01-01T00:00:00Z' + created_at: '2023-01-01T00:00:00Z', }; mockCertApi.createProjectsCertificates.mockResolvedValue(mockCertificate as any); const cert = '-----BEGIN CERTIFICATE-----\nMIIDXTCCAkWgAwIBAgIJAK\n-----END CERTIFICATE-----'; - const key = '-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQ\n-----END PRIVATE KEY-----'; - - const result = await certificateTask.add('project-123', cert, key); + const key = + '-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQ\n-----END PRIVATE KEY-----'; + + const result = await certificatesTask.add('project-123', cert, key); expect(result).toBeDefined(); expect(mockCertApi.createProjectsCertificates).toHaveBeenCalledWith({ projectId: 'project-123', certificateCreateInput: { certificate: cert, key: key, - chain: [] - } + }, }); }); @@ -68,7 +71,7 @@ describe('CertificateTask', () => { const mockCertificate = { id: 'cert-123', certificate: '-----BEGIN CERTIFICATE-----', - created_at: '2023-01-01T00:00:00Z' + created_at: '2023-01-01T00:00:00Z', }; mockCertApi.createProjectsCertificates.mockResolvedValue(mockCertificate as any); @@ -76,16 +79,16 @@ describe('CertificateTask', () => { const cert = '-----BEGIN CERTIFICATE-----\ntest\n-----END CERTIFICATE-----'; const key = '-----BEGIN PRIVATE KEY-----\ntest\n-----END PRIVATE KEY-----'; const chain = ['-----BEGIN CERTIFICATE-----\nchain\n-----END CERTIFICATE-----']; - - const result = await certificateTask.add('project-123', cert, key, chain); + + const result = await certificatesTask.add('project-123', cert, key, { chain }); expect(result).toBeDefined(); expect(mockCertApi.createProjectsCertificates).toHaveBeenCalledWith({ projectId: 'project-123', certificateCreateInput: { certificate: cert, key: key, - chain: chain - } + chain: chain, + }, }); }); @@ -95,22 +98,28 @@ describe('CertificateTask', () => { const cert = '-----BEGIN CERTIFICATE-----\ntest\n-----END CERTIFICATE-----'; const key = '-----BEGIN PRIVATE KEY-----\ntest\n-----END PRIVATE KEY-----'; - await expect(certificateTask.add('project-123', cert, key)).rejects.toThrow('Invalid certificate'); + await expect(certificatesTask.add('project-123', cert, key)).rejects.toThrow( + 'Invalid certificate', + ); }); it('should throw error when certificate is missing', async () => { - await expect(certificateTask.add('project-123', '', 'key')).rejects.toThrow('Certificate and key are required'); + await expect(certificatesTask.add('project-123', '', 'key')).rejects.toThrow( + 'Certificate and key are required', + ); }); it('should throw error when key is missing', async () => { - await expect(certificateTask.add('project-123', 'cert', '')).rejects.toThrow('Certificate and key are required'); + await expect(certificatesTask.add('project-123', 'cert', '')).rejects.toThrow( + 'Certificate and key are required', + ); }); }); describe('delete', () => { it('should have delete method defined', () => { - expect(certificateTask.delete).toBeDefined(); - expect(typeof certificateTask.delete).toBe('function'); + expect(certificatesTask.delete).toBeDefined(); + expect(typeof certificatesTask.delete).toBe('function'); }); it('should delete a certificate from project', async () => { @@ -118,25 +127,27 @@ describe('CertificateTask', () => { mockCertApi.deleteProjectsCertificates.mockResolvedValue(mockResult as any); - const result = await certificateTask.delete('project-123', 'cert-456'); + const result = await certificatesTask.delete('project-123', 'cert-456'); expect(result).toBeDefined(); expect(mockCertApi.deleteProjectsCertificates).toHaveBeenCalledWith({ projectId: 'project-123', - certificateId: 'cert-456' + certificateId: 'cert-456', }); }); it('should handle certificate deletion errors', async () => { mockCertApi.deleteProjectsCertificates.mockRejectedValue(new Error('Certificate not found')); - await expect(certificateTask.delete('project-123', 'cert-456')).rejects.toThrow('Certificate not found'); + await expect(certificatesTask.delete('project-123', 'cert-456')).rejects.toThrow( + 'Certificate not found', + ); }); }); describe('get', () => { it('should have get method defined', () => { - expect(certificateTask.get).toBeDefined(); - expect(typeof certificateTask.get).toBe('function'); + expect(certificatesTask.get).toBeDefined(); + expect(typeof certificatesTask.get).toBe('function'); }); it('should get certificate information', async () => { @@ -144,49 +155,86 @@ describe('CertificateTask', () => { id: 'cert-123', certificate: '-----BEGIN CERTIFICATE-----', domains: ['example.com'], - created_at: '2023-01-01T00:00:00Z' + created_at: '2023-01-01T00:00:00Z', }; mockCertApi.getProjectsCertificates.mockResolvedValue(mockCertificate as any); - const result = await certificateTask.get('project-123', 'cert-456'); + const result = await certificatesTask.get('project-123', 'cert-456'); expect(result).toBeDefined(); expect((result as any).id).toBe('cert-123'); expect(mockCertApi.getProjectsCertificates).toHaveBeenCalledWith({ projectId: 'project-123', - certificateId: 'cert-456' + certificateId: 'cert-456', }); }); }); describe('list', () => { it('should have list method defined', () => { - expect(certificateTask.list).toBeDefined(); - expect(typeof certificateTask.list).toBe('function'); + expect(certificatesTask.list).toBeDefined(); + expect(typeof certificatesTask.list).toBe('function'); }); it('should list project certificates', async () => { const mockCertificates = [ { id: 'cert-123', domains: ['example.com'], created_at: '2023-01-01T00:00:00Z' }, - { id: 'cert-456', domains: ['test.com'], created_at: '2023-01-02T00:00:00Z' } + { id: 'cert-456', domains: ['test.com'], created_at: '2023-01-02T00:00:00Z' }, ]; mockCertApi.listProjectsCertificates.mockResolvedValue(mockCertificates as any); - const result = await certificateTask.list('project-123'); + const result = await certificatesTask.list('project-123'); expect(result).toBeDefined(); expect(result).toHaveLength(2); expect((result[0] as any).id).toBe('cert-123'); expect(mockCertApi.listProjectsCertificates).toHaveBeenCalledWith({ - projectId: 'project-123' + projectId: 'project-123', }); }); it('should handle empty certificate list', async () => { mockCertApi.listProjectsCertificates.mockResolvedValue([]); - const result = await certificateTask.list('project-123'); + const result = await certificatesTask.list('project-123'); expect(result).toEqual([]); }); }); + + describe('update', () => { + it('should have update method defined', () => { + expect(certificatesTask.update).toBeDefined(); + expect(typeof certificatesTask.update).toBe('function'); + }); + + it('should update a certificate', async () => { + const mockResponse = { status: 'ok' }; + mockCertApi.updateProjectsCertificates = jest.fn().mockResolvedValue(mockResponse); + + const isInvalid = false; + const chain = ['-----BEGIN CERTIFICATE-----\nchain\n-----END CERTIFICATE-----']; + + const result = await certificatesTask.update('project-123', 'cert-456', { + chain, + isInvalid, + }); + expect(result).toBe(mockResponse); + expect(mockCertApi.updateProjectsCertificates).toHaveBeenCalledWith({ + projectId: 'project-123', + certificateId: 'cert-456', + certificatePatch: { chain: chain, isInvalid: isInvalid }, + }); + }); + + it('should handle update errors', async () => { + mockCertApi.updateProjectsCertificates = jest + .fn() + .mockRejectedValue(new Error('Update failed')); + const chain = ['-----BEGIN CERTIFICATE-----\nchain\n-----END CERTIFICATE-----']; + const isInvalid = false; + await expect( + certificatesTask.update('project-123', 'cert-456', { chain, isInvalid }), + ).rejects.toThrow('Update failed'); + }); + }); }); diff --git a/tests/unit/tasks/domain.test.ts b/tests/unit/tasks/domain.test.ts deleted file mode 100644 index 8d56ebb..0000000 --- a/tests/unit/tasks/domain.test.ts +++ /dev/null @@ -1,231 +0,0 @@ -import { DomainTask } from '../../../src/core/tasks/domain.js'; -import { UpsunClient } from '../../../src/upsun.js'; -import { DomainManagementApi } from '../../../src/apis-gen/index.js'; - -// Mock the UpsunClient and DomainManagementApi -jest.mock('../../../src/upsun'); -jest.mock('../../../src/apis-gen/index.js'); - -describe('DomainTask', () => { - let domainTask: DomainTask; - let mockClient: jest.Mocked; - let mockDomainApi: jest.Mocked; - - beforeEach(() => { - mockDomainApi = { - createProjectsDomains: jest.fn(), - createProjectsEnvironmentsDomains: jest.fn(), - deleteProjectsDomains: jest.fn(), - deleteProjectsEnvironmentsDomains: jest.fn(), - getProjectsDomains: jest.fn(), - getProjectsEnvironmentsDomains: jest.fn(), - listProjectsDomains: jest.fn(), - listProjectsEnvironmentsDomains: jest.fn() - } as any; - - (DomainManagementApi as jest.MockedClass).mockImplementation(() => mockDomainApi); - - mockClient = { - apiConfig: { - basePath: 'https://api.upsun.com' - } - } as any; - - domainTask = new DomainTask(mockClient); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('add', () => { - it('should have add method defined', () => { - expect(domainTask.add).toBeDefined(); - expect(typeof domainTask.add).toBe('function'); - }); - - it('should add a domain to project', async () => { - const mockDomain = { - name: 'example.com', - ssl: { has_certificate: false }, - created_at: '2023-01-01T00:00:00Z' - }; - - mockDomainApi.createProjectsDomains.mockResolvedValue(mockDomain as any); - - const result = await domainTask.add('project-123', 'example.com'); - expect(result).toBeDefined(); - expect(mockDomainApi.createProjectsDomains).toHaveBeenCalledWith({ - projectId: 'project-123', - domainCreateInput: { name: 'example.com' } - }); - }); - - it('should add a domain to environment', async () => { - const mockDomain = { - name: 'example.com', - ssl: { has_certificate: false }, - created_at: '2023-01-01T00:00:00Z' - }; - - mockDomainApi.createProjectsEnvironmentsDomains.mockResolvedValue(mockDomain as any); - - const result = await domainTask.add('project-123', 'example.com', 'env-456'); - expect(result).toBeDefined(); - expect(mockDomainApi.createProjectsEnvironmentsDomains).toHaveBeenCalledWith({ - projectId: 'project-123', - environmentId: 'env-456', - domainCreateInput: { name: 'example.com' } - }); - }); - - it('should handle domain addition errors', async () => { - mockDomainApi.createProjectsDomains.mockRejectedValue(new Error('Domain already exists')); - - await expect(domainTask.add('project-123', 'example.com')).rejects.toThrow('Domain already exists'); - }); - }); - - describe('delete', () => { - it('should have delete method defined', () => { - expect(domainTask.delete).toBeDefined(); - expect(typeof domainTask.delete).toBe('function'); - }); - - it('should delete a domain from project', async () => { - const mockResult = { success: true }; - - mockDomainApi.deleteProjectsDomains.mockResolvedValue(mockResult as any); - - const result = await domainTask.delete('project-123', 'domain-456'); - expect(result).toBeDefined(); - expect(mockDomainApi.deleteProjectsDomains).toHaveBeenCalledWith({ - projectId: 'project-123', - domainId: 'domain-456' - }); - }); - - it('should delete a domain from environment', async () => { - const mockResult = { success: true }; - - mockDomainApi.deleteProjectsEnvironmentsDomains.mockResolvedValue(mockResult as any); - - const result = await domainTask.delete('project-123', 'domain-456', 'env-789'); - expect(result).toBeDefined(); - expect(mockDomainApi.deleteProjectsEnvironmentsDomains).toHaveBeenCalledWith({ - projectId: 'project-123', - environmentId: 'env-789', - domainId: 'domain-456' - }); - }); - - it('should handle domain deletion errors', async () => { - mockDomainApi.deleteProjectsDomains.mockRejectedValue(new Error('Domain not found')); - - await expect(domainTask.delete('project-123', 'domain-456')).rejects.toThrow('Domain not found'); - }); - }); - - describe('get', () => { - it('should have get method defined', () => { - expect(domainTask.get).toBeDefined(); - expect(typeof domainTask.get).toBe('function'); - }); - - it('should get domain information', async () => { - const mockDomain = { - name: 'example.com', - ssl: { has_certificate: true }, - created_at: '2023-01-01T00:00:00Z' - }; - - mockDomainApi.getProjectsDomains.mockResolvedValue(mockDomain as any); - - const result = await domainTask.get('project-123', 'domain-456'); - expect(result).toBeDefined(); - expect((result as any).name).toBe('example.com'); - expect(mockDomainApi.getProjectsDomains).toHaveBeenCalledWith({ - projectId: 'project-123', - domainId: 'domain-456' - }); - }); - - it('should get environment domain information', async () => { - const mockDomain = { - name: 'example.com', - ssl: { has_certificate: true }, - created_at: '2023-01-01T00:00:00Z' - }; - - mockDomainApi.getProjectsEnvironmentsDomains.mockResolvedValue(mockDomain as any); - - const result = await domainTask.get('project-123', 'domain-456', 'env-789'); - expect(result).toBeDefined(); - expect((result as any).name).toBe('example.com'); - expect(mockDomainApi.getProjectsEnvironmentsDomains).toHaveBeenCalledWith({ - projectId: 'project-123', - environmentId: 'env-789', - domainId: 'domain-456' - }); - }); - }); - - describe('list', () => { - it('should have list method defined', () => { - expect(domainTask.list).toBeDefined(); - expect(typeof domainTask.list).toBe('function'); - }); - - it('should list project domains', async () => { - const mockDomains = [ - { name: 'example.com', ssl: { has_certificate: true } }, - { name: 'test.com', ssl: { has_certificate: false } } - ]; - - mockDomainApi.listProjectsDomains.mockResolvedValue(mockDomains as any); - - const result = await domainTask.list('project-123'); - expect(result).toBeDefined(); - expect(result).toHaveLength(2); - expect((result[0] as any).name).toBe('example.com'); - expect(mockDomainApi.listProjectsDomains).toHaveBeenCalledWith({ - projectId: 'project-123' - }); - }); - - it('should list environment domains', async () => { - const mockDomains = [ - { name: 'env-example.com', ssl: { has_certificate: true } } - ]; - - mockDomainApi.listProjectsEnvironmentsDomains.mockResolvedValue(mockDomains as any); - - const result = await domainTask.list('project-123', 'env-456'); - expect(result).toBeDefined(); - expect(result).toHaveLength(1); - expect((result[0] as any).name).toBe('env-example.com'); - expect(mockDomainApi.listProjectsEnvironmentsDomains).toHaveBeenCalledWith({ - projectId: 'project-123', - environmentId: 'env-456' - }); - }); - - it('should handle empty domain list', async () => { - mockDomainApi.listProjectsDomains.mockResolvedValue([]); - - const result = await domainTask.list('project-123'); - expect(result).toEqual([]); - }); - }); - - describe('update', () => { - it('should have update method defined', () => { - expect(domainTask.update).toBeDefined(); - expect(typeof domainTask.update).toBe('function'); - }); - - it('should throw "Method not implemented" error', async () => { - await expect(domainTask.update('project-123', 'example.com')).rejects.toThrow('Method not implemented.'); - }); - }); -}); diff --git a/tests/unit/tasks/domains.test.ts b/tests/unit/tasks/domains.test.ts new file mode 100644 index 0000000..82c8a3c --- /dev/null +++ b/tests/unit/tasks/domains.test.ts @@ -0,0 +1,393 @@ +import { DomainsTask } from '../../../src/core/tasks/domains.js'; +import { UpsunClient } from '../../../src/upsun.js'; +import { DomainManagementApi } from '../../../src/api/index.js'; + +// Mock the UpsunClient and DomainManagementApi +jest.mock('../../../src/upsun.js'); +jest.mock('../../../src/api/index.js'); + +describe('DomainsTask', () => { + let domainsTask: DomainsTask; + let mockClient: jest.Mocked; + let mockDomainApi: jest.Mocked; + + beforeEach(() => { + mockDomainApi = { + createProjectsDomains: jest.fn(), + createProjectsEnvironmentsDomains: jest.fn(), + deleteProjectsDomains: jest.fn(), + deleteProjectsEnvironmentsDomains: jest.fn(), + getProjectsDomains: jest.fn(), + getProjectsEnvironmentsDomains: jest.fn(), + listProjectsDomains: jest.fn(), + listProjectsEnvironmentsDomains: jest.fn(), + updateProjectsDomains: jest.fn(), + updateProjectsEnvironmentsDomains: jest.fn(), + } as any; + + (DomainManagementApi as jest.MockedClass).mockImplementation( + () => mockDomainApi, + ); + + mockClient = { + apiConfig: { + basePath: 'https://api.upsun.com', + }, + } as any; + + domainsTask = new DomainsTask(mockClient, mockDomainApi); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('add', () => { + it('should have add method defined', () => { + expect(domainsTask.add).toBeDefined(); + expect(typeof domainsTask.add).toBe('function'); + }); + + it('should add a domain to project with minimal parameters', async () => { + const mockDomain = { + name: 'example.com', + ssl: { has_certificate: false }, + created_at: '2023-01-01T00:00:00Z', + }; + + mockDomainApi.createProjectsDomains.mockResolvedValue(mockDomain as any); + + const result = await domainsTask.add('project-123', 'example.com'); + expect(result).toBeDefined(); + expect(mockDomainApi.createProjectsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + domainCreateInput: { + name: 'example.com', + attributes: undefined, + isDefault: undefined, + replacementFor: undefined, + }, + }); + }); + + it('should add a domain to project with all parameters', async () => { + const mockDomain = { + name: 'example.com', + ssl: { has_certificate: false }, + created_at: '2023-01-01T00:00:00Z', + }; + + mockDomainApi.createProjectsDomains.mockResolvedValue(mockDomain as any); + + const attributes = { cdn: 'enabled' }; + const result = await domainsTask.add( + 'project-123', + 'example.com', + attributes, + true, + 'old-domain.com', + ); + expect(result).toBeDefined(); + expect(mockDomainApi.createProjectsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + domainCreateInput: { + name: 'example.com', + attributes: attributes, + isDefault: true, + replacementFor: 'old-domain.com', + }, + }); + }); + + it('should add a domain to environment with minimal parameters', async () => { + const mockDomain = { + name: 'example.com', + ssl: { has_certificate: false }, + created_at: '2023-01-01T00:00:00Z', + }; + + mockDomainApi.createProjectsEnvironmentsDomains.mockResolvedValue(mockDomain as any); + + const result = await domainsTask.add('project-123', 'example.com', {}, false, '', 'env-456'); + expect(result).toBeDefined(); + expect(mockDomainApi.createProjectsEnvironmentsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'env-456', + domainCreateInput: { + name: 'example.com', + attributes: {}, + isDefault: false, + replacementFor: '', + }, + }); + }); + + it('should add a domain to environment with all parameters', async () => { + const mockDomain = { + name: 'env-example.com', + ssl: { has_certificate: true }, + created_at: '2023-01-01T00:00:00Z', + }; + + mockDomainApi.createProjectsEnvironmentsDomains.mockResolvedValue(mockDomain as any); + + const attributes = { ssl: 'auto', cache: 'enabled' }; + const result = await domainsTask.add( + 'project-123', + 'env-example.com', + attributes, + true, + 'old-env-domain.com', + 'env-456', + ); + expect(result).toBeDefined(); + expect(mockDomainApi.createProjectsEnvironmentsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'env-456', + domainCreateInput: { + name: 'env-example.com', + attributes: attributes, + isDefault: true, + replacementFor: 'old-env-domain.com', + }, + }); + }); + + it('should handle domain addition errors', async () => { + mockDomainApi.createProjectsDomains.mockRejectedValue(new Error('Domain already exists')); + + await expect(domainsTask.add('project-123', 'example.com')).rejects.toThrow( + 'Domain already exists', + ); + }); + + it('should throw error when domain is empty', async () => { + await expect(domainsTask.add('project-123', '')).rejects.toThrow( + 'Domain must be a non-empty string', + ); + }); + }); + + describe('delete', () => { + it('should have delete method defined', () => { + expect(domainsTask.delete).toBeDefined(); + expect(typeof domainsTask.delete).toBe('function'); + }); + + it('should delete a domain from project', async () => { + const mockResult = { success: true }; + + mockDomainApi.deleteProjectsDomains.mockResolvedValue(mockResult as any); + + const result = await domainsTask.delete('project-123', 'domain-456'); + expect(result).toBeDefined(); + expect(mockDomainApi.deleteProjectsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + domainId: 'domain-456', + }); + }); + + it('should delete a domain from environment', async () => { + const mockResult = { success: true }; + + mockDomainApi.deleteProjectsEnvironmentsDomains.mockResolvedValue(mockResult as any); + + const result = await domainsTask.delete('project-123', 'domain-456', 'env-789'); + expect(result).toBeDefined(); + expect(mockDomainApi.deleteProjectsEnvironmentsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'env-789', + domainId: 'domain-456', + }); + }); + + it('should handle domain deletion errors', async () => { + mockDomainApi.deleteProjectsDomains.mockRejectedValue(new Error('Domain not found')); + + await expect(domainsTask.delete('project-123', 'domain-456')).rejects.toThrow( + 'Domain not found', + ); + }); + }); + + describe('get', () => { + it('should have get method defined', () => { + expect(domainsTask.get).toBeDefined(); + expect(typeof domainsTask.get).toBe('function'); + }); + + it('should get domain information', async () => { + const mockDomain = { + name: 'example.com', + ssl: { has_certificate: true }, + created_at: '2023-01-01T00:00:00Z', + }; + + mockDomainApi.getProjectsDomains.mockResolvedValue(mockDomain as any); + + const result = await domainsTask.get('project-123', 'domain-456'); + expect(result).toBeDefined(); + expect((result as any).name).toBe('example.com'); + expect(mockDomainApi.getProjectsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + domainId: 'domain-456', + }); + }); + + it('should get environment domain information', async () => { + const mockDomain = { + name: 'example.com', + ssl: { has_certificate: true }, + created_at: '2023-01-01T00:00:00Z', + }; + + mockDomainApi.getProjectsEnvironmentsDomains.mockResolvedValue(mockDomain as any); + + const result = await domainsTask.get('project-123', 'domain-456', 'env-789'); + expect(result).toBeDefined(); + expect((result as any).name).toBe('example.com'); + expect(mockDomainApi.getProjectsEnvironmentsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'env-789', + domainId: 'domain-456', + }); + }); + }); + + describe('list', () => { + it('should have list method defined', () => { + expect(domainsTask.list).toBeDefined(); + expect(typeof domainsTask.list).toBe('function'); + }); + + it('should list project domains', async () => { + const mockDomains = [ + { name: 'example.com', ssl: { has_certificate: true } }, + { name: 'test.com', ssl: { has_certificate: false } }, + ]; + + mockDomainApi.listProjectsDomains.mockResolvedValue(mockDomains as any); + + const result = await domainsTask.list('project-123'); + expect(result).toBeDefined(); + expect(result).toHaveLength(2); + expect((result[0] as any).name).toBe('example.com'); + expect(mockDomainApi.listProjectsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + }); + }); + + it('should list environment domains', async () => { + const mockDomains = [{ name: 'env-example.com', ssl: { has_certificate: true } }]; + + mockDomainApi.listProjectsEnvironmentsDomains.mockResolvedValue(mockDomains as any); + + const result = await domainsTask.list('project-123', 'env-456'); + expect(result).toBeDefined(); + expect(result).toHaveLength(1); + expect((result[0] as any).name).toBe('env-example.com'); + expect(mockDomainApi.listProjectsEnvironmentsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'env-456', + }); + }); + + it('should handle empty domain list', async () => { + mockDomainApi.listProjectsDomains.mockResolvedValue([]); + + const result = await domainsTask.list('project-123'); + expect(result).toEqual([]); + }); + }); + + describe('update', () => { + it('should have update method defined', () => { + expect(domainsTask.update).toBeDefined(); + expect(typeof domainsTask.update).toBe('function'); + }); + + it('should update a project domain', async () => { + const mockActivity = { + id: 'activity-update-123', + type: 'domain.update', + }; + + mockDomainApi.updateProjectsDomains.mockResolvedValue(mockActivity as any); + + const attributes = { cdn: 'enabled' }; + const result = await domainsTask.update('project-123', 'domain-456', { + attributes: attributes, + isDefault: true, + }); + + expect(result).toBeDefined(); + expect(result).toEqual(mockActivity); + expect(mockDomainApi.updateProjectsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + domainId: 'domain-456', + domainPatch: { + attributes: attributes, + isDefault: true, + }, + }); + }); + + it('should update an environment domain', async () => { + const mockActivity = { + id: 'activity-update-456', + type: 'domain.update', + }; + + mockDomainApi.updateProjectsEnvironmentsDomains.mockResolvedValue(mockActivity as any); + + const attributes = { ssl: 'auto' }; + const result = await domainsTask.update( + 'project-123', + 'domain-456', + { + attributes: attributes, + isDefault: false, + }, + 'env-789', + ); + + expect(result).toBeDefined(); + expect(result).toEqual(mockActivity); + expect(mockDomainApi.updateProjectsEnvironmentsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'env-789', + domainId: 'domain-456', + domainPatch: { + attributes: attributes, + isDefault: false, + }, + }); + }); + + it('should update domain with default parameters', async () => { + const mockActivity = { + id: 'activity-update-789', + type: 'domain.update', + }; + + mockDomainApi.updateProjectsDomains.mockResolvedValue(mockActivity as any); + + const result = await domainsTask.update('project-123', 'domain-456'); + + expect(result).toBeDefined(); + expect(mockDomainApi.updateProjectsDomains).toHaveBeenCalledWith({ + projectId: 'project-123', + domainId: 'domain-456', + domainPatch: {}, + }); + }); + + it('should handle domain update errors', async () => { + mockDomainApi.updateProjectsDomains.mockRejectedValue(new Error('Update failed')); + + await expect(domainsTask.update('project-123', 'domain-456')).rejects.toThrow( + 'Update failed', + ); + }); + }); +}); diff --git a/tests/unit/tasks/environment.test.ts b/tests/unit/tasks/environment.test.ts deleted file mode 100644 index 68288d4..0000000 --- a/tests/unit/tasks/environment.test.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { EnvironementTask } from '../../../src/core/tasks/environment.js'; -import { UpsunClient } from '../../../src/upsun.js'; -import { EnvironmentApi } from '../../../src/apis-gen/index.js'; - -// Mock the UpsunClient and EnvironmentApi -jest.mock('../../../src/upsun'); -jest.mock('../../../src/apis-gen/index.js'); - -describe('EnvironementTask', () => { - let environmentTask: EnvironementTask; - let mockClient: jest.Mocked; - let mockEnvironmentApi: jest.Mocked; - - beforeEach(() => { - mockEnvironmentApi = { - listProjectsEnvironments: jest.fn(), - getEnvironment: jest.fn(), - activateEnvironment: jest.fn(), - pauseEnvironment: jest.fn(), - resumeEnvironment: jest.fn(), - deleteProjectsEnvironments: jest.fn(), - redeployEnvironment: jest.fn(), - mergeEnvironment: jest.fn(), - deactivateEnvironment: jest.fn() - } as any; - - (EnvironmentApi as jest.MockedClass).mockImplementation(() => mockEnvironmentApi); - - mockClient = { - apiConfig: { - basePath: 'https://api.upsun.com' - } - } as any; - - environmentTask = new EnvironementTask(mockClient); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('list', () => { - it('should have list method defined', () => { - expect(environmentTask.list).toBeDefined(); - expect(typeof environmentTask.list).toBe('function'); - }); - - it('should list project environments', async () => { - const mockEnvironments = [ - { id: 'env-1', name: 'main' }, - { id: 'env-2', name: 'staging' } - ]; - - mockEnvironmentApi.listProjectsEnvironments.mockResolvedValue(mockEnvironments as any); - - const result = await environmentTask.list('project-123'); - expect(result).toBeDefined(); - expect(result).toHaveLength(2); - expect(mockEnvironmentApi.listProjectsEnvironments).toHaveBeenCalledWith({ - projectId: 'project-123' - }); - }); - }); - - describe('info', () => { - it('should have info method defined', () => { - expect(environmentTask.info).toBeDefined(); - expect(typeof environmentTask.info).toBe('function'); - }); - - it('should get environment information', async () => { - const mockEnvironment = { - id: 'env-123', - name: 'main', - status: 'active' - }; - - mockEnvironmentApi.getEnvironment.mockResolvedValue(mockEnvironment as any); - - const result = await environmentTask.info('project-123', 'main'); - expect(result).toBeDefined(); - expect((result as any).id).toBe('env-123'); - expect(mockEnvironmentApi.getEnvironment).toHaveBeenCalledWith({ - projectId: 'project-123', - environmentId: 'main' - }); - }); - }); - - describe('activate', () => { - it('should have activate method defined', () => { - expect(environmentTask.activate).toBeDefined(); - expect(typeof environmentTask.activate).toBe('function'); - }); - it('should activate an environment', async () => { - expect(environmentTask.activate).toBeDefined(); - expect(typeof environmentTask.activate).toBe('function'); - }); - }); - - describe('deactivate', () => { - it('should deactivate an environment', async () => { - expect(environmentTask.deactivate).toBeDefined(); - expect(typeof environmentTask.deactivate).toBe('function'); - }); - }); - - describe('delete', () => { - it('should delete an environment', async () => { - expect(environmentTask.delete).toBeDefined(); - expect(typeof environmentTask.delete).toBe('function'); - }); - }); - - describe('merge', () => { - it('should merge an environment', async () => { - expect(environmentTask.merge).toBeDefined(); - expect(typeof environmentTask.merge).toBe('function'); - }); - }); - - describe('pause', () => { - it('should pause an environment', async () => { - expect(environmentTask.pause).toBeDefined(); - expect(typeof environmentTask.pause).toBe('function'); - }); - }); - - describe('resume', () => { - it('should resume an environment', async () => { - expect(environmentTask.resume).toBeDefined(); - expect(typeof environmentTask.resume).toBe('function'); - }); - }); - - describe('redeploy', () => { - it('should redeploy an environment', async () => { - expect(environmentTask.redeploy).toBeDefined(); - expect(typeof environmentTask.redeploy).toBe('function'); - }); - }); - - describe('logs', () => { - it('should throw not implemented error', async () => { - await expect(environmentTask.logs('project-123', 'main', 'app')).rejects.toThrow('Not implemented'); - }); - }); - - describe('relationships', () => { - it('should throw not implemented error', async () => { - await expect(environmentTask.relationships('project-123', 'main')).rejects.toThrow('Not implemented'); - }); - }); - - describe('urls', () => { - it('should throw not implemented error', async () => { - await expect(environmentTask.urls('project-123', 'main')).rejects.toThrow('Not implemented'); - }); - }); -}); diff --git a/tests/unit/tasks/environments.test.ts b/tests/unit/tasks/environments.test.ts new file mode 100644 index 0000000..7b909a0 --- /dev/null +++ b/tests/unit/tasks/environments.test.ts @@ -0,0 +1,683 @@ +import { EnvironmentsTask } from '../../../src/core/tasks/environments.js'; +import { UpsunClient } from '../../../src/upsun.js'; +import { + AutoscalingApi, + DeploymentApi, + EnvironmentApi, + EnvironmentTypeApi, +} from '../../../src/api/index.js'; +import { + AddressGrantsInnerPermissionEnum, + EnvironmentPatchTypeEnum, + EnvironmentBranchInputTypeEnum, + Resources3InitEnum, + Resources4InitEnum, + Resources5InitEnum, +} from '../../../src/model/index.js'; + +jest.mock('../../../src/upsun'); +jest.mock('../../../src/api/index.js'); + +describe('EnvironmentsTask', () => { + let environmentTask: EnvironmentsTask; + let mockClient: jest.Mocked; + let mockVariables: { + createEnvironmentVariable: jest.Mock; + deleteEnvironmentVariable: jest.Mock; + getEnvironmentVariable: jest.Mock; + listEnvironmentVariables: jest.Mock; + updateEnvironmentVariable: jest.Mock; + }; + let mockRoutes: { + get: jest.Mock; + list: jest.Mock; + }; + let mockDomains: { + add: jest.Mock; + delete: jest.Mock; + get: jest.Mock; + list: jest.Mock; + update: jest.Mock; + }; + let mockEnvironmentApi: jest.Mocked; + let mockEnvironmentTypeApi: jest.Mocked; + let mockDeploymentApi: jest.Mocked; + let mockAutoscalingApi: jest.Mocked; + + beforeEach(() => { + mockEnvironmentApi = { + listProjectsEnvironments: jest.fn(), + getEnvironment: jest.fn(), + activateEnvironment: jest.fn(), + branchEnvironment: jest.fn(), + initializeEnvironment: jest.fn(), + deactivateEnvironment: jest.fn(), + deleteEnvironment: jest.fn(), + mergeEnvironment: jest.fn(), + pauseEnvironment: jest.fn(), + resumeEnvironment: jest.fn(), + redeployEnvironment: jest.fn(), + synchronizeEnvironment: jest.fn(), + updateEnvironment: jest.fn(), + } as any; + + mockEnvironmentTypeApi = { + getEnvironmentType: jest.fn(), + } as any; + + mockDeploymentApi = { + getProjectsEnvironmentsDeployments: jest.fn(), + listProjectsEnvironmentsDeployments: jest.fn(), + } as any; + + mockAutoscalingApi = {} as any; + + (EnvironmentApi as jest.MockedClass).mockImplementation( + () => mockEnvironmentApi, + ); + (EnvironmentTypeApi as jest.MockedClass).mockImplementation( + () => mockEnvironmentTypeApi, + ); + (DeploymentApi as jest.MockedClass).mockImplementation( + () => mockDeploymentApi, + ); + (AutoscalingApi as jest.MockedClass).mockImplementation( + () => mockAutoscalingApi, + ); + + mockVariables = { + createEnvironmentVariable: jest.fn(), + deleteEnvironmentVariable: jest.fn(), + getEnvironmentVariable: jest.fn(), + listEnvironmentVariables: jest.fn(), + updateEnvironmentVariable: jest.fn(), + }; + + mockRoutes = { + get: jest.fn(), + list: jest.fn(), + }; + + mockDomains = { + add: jest.fn(), + delete: jest.fn(), + get: jest.fn(), + list: jest.fn(), + update: jest.fn(), + }; + + mockClient = { + apiConfig: { + basePath: 'https://api.upsun.com', + }, + variables: mockVariables, + routes: mockRoutes, + domains: mockDomains, + } as any; + + environmentTask = new EnvironmentsTask( + mockClient, + mockEnvironmentApi, + mockEnvironmentTypeApi, + mockDeploymentApi, + ); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('constructor', () => { + it('should initialize properly', () => { + expect(environmentTask).toBeDefined(); + expect(environmentTask).toBeInstanceOf(EnvironmentsTask); + }); + }); + + describe('activate', () => { + it('should call activate API', async () => { + const mockResponse = { status: 'ok' } as any; + mockEnvironmentApi.activateEnvironment.mockResolvedValue(mockResponse); + + const result = await environmentTask.activate('project-123', 'main', 'INIT_VAL'); + expect(result).toBe(mockResponse); + expect(mockEnvironmentApi.activateEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + environmentActivateInput: { + resources: { init: 'INIT_VAL' }, + }, + }); + }); + + it('should use default init if not provided', async () => { + mockEnvironmentApi.activateEnvironment.mockResolvedValue({} as any); + + await environmentTask.activate('project-123', 'main'); + expect(mockEnvironmentApi.activateEnvironment).toHaveBeenCalledWith( + expect.objectContaining({ + environmentActivateInput: expect.objectContaining({ + resources: { init: undefined }, + }), + }), + ); + }); + }); + + describe('branch', () => { + it('should branch an environment', async () => { + const mockResponse = { status: 'ok', code: 202 }; + mockEnvironmentApi.branchEnvironment.mockResolvedValue(mockResponse as any); + + const result = await environmentTask.branch( + 'project-123', + 'main', + 'My Title', + 'my-env', + true, + EnvironmentBranchInputTypeEnum.DEVELOPMENT, + Resources3InitEnum.PARENT, + ); + expect(result).toBe(mockResponse); + expect(mockEnvironmentApi.branchEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + environmentBranchInput: { + title: 'My Title', + name: 'my-env', + cloneParent: true, + type: EnvironmentBranchInputTypeEnum.DEVELOPMENT, + resources: { init: Resources3InitEnum.PARENT }, + }, + }); + }); + + it('should throw error if title is empty', async () => { + await expect(environmentTask.branch('project-123', 'main', '', 'my-env')).rejects.toThrow( + 'Title must be a non-empty string', + ); + }); + + it('should throw error if name is empty', async () => { + await expect(environmentTask.branch('project-123', 'main', 'My Title', '')).rejects.toThrow( + 'Name must be a non-empty string', + ); + }); + }); + + describe('init', () => { + it('should initialize an environment', async () => { + const mockResponse = { status: 'ok', code: 202 }; + mockEnvironmentApi.initializeEnvironment.mockResolvedValue(mockResponse as any); + const files = [ + { path: 'file1.txt', mode: 420, contents: 'content1' }, + { path: 'file2.txt', mode: 420, contents: 'content2' }, + ]; + + const result = await environmentTask.init( + 'project-123', + 'main', + 'profile', + 'repo', + files, + 'configVal', + Resources4InitEnum.DEFAULT, + ); + expect(result).toBe(mockResponse); + expect(mockEnvironmentApi.initializeEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + environmentInitializeInput: { + profile: 'profile', + repository: 'repo', + config: 'configVal', + resources: { init: Resources4InitEnum.DEFAULT }, + files: files, + }, + }); + }); + + it('should throw error if profile is empty', async () => { + await expect( + environmentTask.init('project-123', 'main', '', 'repo', [ + { path: 'f', mode: 420, contents: 'c' }, + ]), + ).rejects.toThrow('Profile must be a non-empty string'); + }); + + it('should throw error if repository is empty', async () => { + await expect( + environmentTask.init('project-123', 'main', 'profile', '', [ + { path: 'f', mode: 420, contents: 'c' }, + ]), + ).rejects.toThrow('Repository must be a non-empty string'); + }); + + it('should throw error if files is empty', async () => { + await expect( + environmentTask.init('project-123', 'main', 'profile', 'repo', []), + ).rejects.toThrow('Files must be a non-empty array of [filePath, fileMode, fileContents]'); + }); + + it('should use default init if not provided', async () => { + mockEnvironmentApi.initializeEnvironment.mockResolvedValue({} as any); + await environmentTask.init('project-123', 'main', 'profile', 'repo', [ + { path: 'f', mode: 420, contents: 'c' }, + ]); + expect(mockEnvironmentApi.initializeEnvironment).toHaveBeenCalledWith( + expect.objectContaining({ + environmentInitializeInput: expect.objectContaining({ + resources: { init: Resources4InitEnum.DEFAULT }, + }), + }), + ); + }); + }); + + describe('list', () => { + it('should list project environments', async () => { + const mockEnvironments = [ + { id: 'env-1', name: 'main' }, + { id: 'env-2', name: 'staging' }, + ]; + + mockEnvironmentApi.listProjectsEnvironments.mockResolvedValue(mockEnvironments as any); + + const result = await environmentTask.list('project-123'); + expect(result).toBeDefined(); + expect(result).toHaveLength(2); + expect(mockEnvironmentApi.listProjectsEnvironments).toHaveBeenCalledWith({ + projectId: 'project-123', + }); + }); + }); + + describe('info', () => { + it('should get environment information', async () => { + const mockEnvironment = { + id: 'env-123', + name: 'main', + status: 'active', + }; + + mockEnvironmentApi.getEnvironment.mockResolvedValue(mockEnvironment as any); + + const result = await environmentTask.info('project-123', 'main'); + expect(result).toBeDefined(); + expect((result as any).id).toBe('env-123'); + expect(mockEnvironmentApi.getEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + }); + }); + }); + + describe('get', () => { + it('should get environment information', async () => { + const mockEnvironment = { id: 'env-1' }; + mockEnvironmentApi.getEnvironment.mockResolvedValue(mockEnvironment as any); + + const result = await environmentTask.get('project-123', 'main'); + expect(result).toBe(mockEnvironment); + expect(mockEnvironmentApi.getEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + }); + }); + }); + + describe('deactivate', () => { + it('should deactivate an environment', async () => { + mockEnvironmentApi.deactivateEnvironment.mockResolvedValue({} as any); + await environmentTask.deactivate('project-123', 'main'); + expect(mockEnvironmentApi.deactivateEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + }); + }); + }); + + describe('delete', () => { + it('should delete an environment', async () => { + mockEnvironmentApi.deleteEnvironment.mockResolvedValue({} as any); + await environmentTask.delete('project-123', 'main'); + expect(mockEnvironmentApi.deleteEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + }); + }); + }); + + describe('merge', () => { + it('should merge an environment', async () => { + mockEnvironmentApi.mergeEnvironment.mockResolvedValue({} as any); + await environmentTask.merge('project-123', 'main', Resources5InitEnum.CHILD); + expect(mockEnvironmentApi.mergeEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + environmentMergeInput: { + resources: { init: Resources5InitEnum.CHILD }, + }, + }); + }); + + it('should use default init if not provided', async () => { + mockEnvironmentApi.mergeEnvironment.mockResolvedValue({} as any); + await environmentTask.merge('project-123', 'main'); + expect(mockEnvironmentApi.mergeEnvironment).toHaveBeenCalledWith( + expect.objectContaining({ + environmentMergeInput: expect.objectContaining({ + resources: { init: Resources5InitEnum.DEFAULT }, + }), + }), + ); + }); + }); + + describe('pause', () => { + it('should pause an environment', async () => { + mockEnvironmentApi.pauseEnvironment.mockResolvedValue({} as any); + await environmentTask.pause('project-123', 'main'); + expect(mockEnvironmentApi.pauseEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + }); + }); + }); + + describe('resume', () => { + it('should resume an environment', async () => { + mockEnvironmentApi.resumeEnvironment.mockResolvedValue({} as any); + await environmentTask.resume('project-123', 'main'); + expect(mockEnvironmentApi.resumeEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + }); + }); + }); + + describe('redeploy', () => { + it('should redeploy an environment', async () => { + mockEnvironmentApi.redeployEnvironment.mockResolvedValue({} as any); + await environmentTask.redeploy('project-123', 'main'); + expect(mockEnvironmentApi.redeployEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + }); + }); + }); + + describe('synchronize', () => { + it('should synchronize an environment', async () => { + mockEnvironmentApi.synchronizeEnvironment.mockResolvedValue({} as any); + await environmentTask.synchronize('project-123', 'main', false, true, false, true); + expect(mockEnvironmentApi.synchronizeEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + environmentSynchronizeInput: { + synchronizeCode: false, + rebase: true, + synchronizeData: false, + synchronizeResources: true, + }, + }); + }); + }); + + describe('update', () => { + it('should update an environment', async () => { + mockEnvironmentApi.updateEnvironment.mockResolvedValue({} as any); + const params = { + parent: 'parent', + name: 'name', + title: 'title', + attributes: { key: 'value' }, + type: EnvironmentPatchTypeEnum.DEVELOPMENT, + cloneParentOnCreate: true, + httpAccess: { + isEnabled: true, + addresses: [{ address: '1.2.3.4', permission: AddressGrantsInnerPermissionEnum.ALLOW }], + basicAuth: { username: 'user', password: 'pass' }, + }, + enableSmtp: true, + restrictRobots: false, + }; + + await environmentTask.update('project-123', 'main', params); + + expect(mockEnvironmentApi.updateEnvironment).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + environmentPatch: params, + }); + }); + }); + + describe('getType', () => { + it('should get environment type', async () => { + const response = { id: 'type-1' } as any; + mockEnvironmentTypeApi.getEnvironmentType.mockResolvedValue(response); + + const result = await environmentTask.getType('project-123', 'type-1'); + expect(result).toBe(response); + expect(mockEnvironmentTypeApi.getEnvironmentType).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentTypeId: 'type-1', + }); + }); + }); + + describe('variables passthrough', () => { + it('should create environment variable via client', async () => { + const response = { ok: true } as any; + mockVariables.createEnvironmentVariable.mockResolvedValue(response); + + const result = await environmentTask.createVariables('project-123', 'main', 'NAME', 'VALUE', { + attributes: { env: 'true' }, + isJson: true, + }); + expect(result).toBe(response); + expect(mockVariables.createEnvironmentVariable).toHaveBeenCalledWith( + 'project-123', + 'main', + 'NAME', + 'VALUE', + { attributes: { env: 'true' }, isJson: true }, + ); + }); + + it('should delete environment variable via client', async () => { + mockVariables.deleteEnvironmentVariable.mockResolvedValue({} as any); + await environmentTask.deleteVariable('project-123', 'main', 'var-1'); + expect(mockVariables.deleteEnvironmentVariable).toHaveBeenCalledWith( + 'project-123', + 'main', + 'var-1', + ); + }); + + it('should get environment variable via client', async () => { + const response = { id: 'var-1' } as any; + mockVariables.getEnvironmentVariable.mockResolvedValue(response); + const result = await environmentTask.getVariable('project-123', 'main', 'var-1'); + expect(result).toBe(response); + expect(mockVariables.getEnvironmentVariable).toHaveBeenCalledWith( + 'project-123', + 'main', + 'var-1', + ); + }); + + it('should list environment variables via client', async () => { + const response = [{ id: 'var-1' }] as any; + mockVariables.listEnvironmentVariables.mockResolvedValue(response); + const result = await environmentTask.listVariables('project-123', 'main'); + expect(result).toBe(response); + expect(mockVariables.listEnvironmentVariables).toHaveBeenCalledWith('project-123', 'main'); + }); + + it('should update environment variable via client', async () => { + const response = { ok: true } as any; + mockVariables.updateEnvironmentVariable.mockResolvedValue(response); + const result = await environmentTask.updateVariable( + 'project-123', + 'main', + 'var-1', + 'NAME', + 'VALUE', + { attributes: { env: 'true' }, isJson: true }, + ); + expect(result).toBe(response); + expect(mockVariables.updateEnvironmentVariable).toHaveBeenCalledWith( + 'project-123', + 'main', + 'var-1', + 'NAME', + 'VALUE', + { attributes: { env: 'true' }, isJson: true }, + ); + }); + }); + + describe('routes passthrough', () => { + it('should get route via client', async () => { + const response = { id: 'route-1' } as any; + mockRoutes.get.mockResolvedValue(response); + const result = await environmentTask.getRoute('project-123', 'main', 'route-1'); + expect(result).toBe(response); + expect(mockRoutes.get).toHaveBeenCalledWith('project-123', 'main', 'route-1'); + }); + + it('should list routes via client', async () => { + const response = [{ id: 'route-1' }] as any; + mockRoutes.list.mockResolvedValue(response); + const result = await environmentTask.listRoutes('project-123', 'main'); + expect(result).toBe(response); + expect(mockRoutes.list).toHaveBeenCalledWith('project-123', 'main'); + }); + }); + + describe('domains passthrough', () => { + it('should pass domain creation to client', async () => { + mockDomains.add.mockResolvedValue({} as any); + await environmentTask.createDomain('project-123', 'main', ''); + expect(mockDomains.add).toHaveBeenCalledWith( + 'project-123', + '', + undefined, + undefined, + undefined, + 'main', + ); + }); + + it('should create domain via client', async () => { + const response = { ok: true } as any; + mockDomains.add.mockResolvedValue(response); + const result = await environmentTask.createDomain( + 'project-123', + 'main', + 'example.com', + { env: 'true' }, + true, + 'old.example.com', + ); + expect(result).toBe(response); + expect(mockDomains.add).toHaveBeenCalledWith( + 'project-123', + 'example.com', + { env: 'true' }, + true, + 'old.example.com', + 'main', + ); + }); + + it('should delete domain via client', async () => { + mockDomains.delete.mockResolvedValue({} as any); + await environmentTask.deleteDomain('project-123', 'main', 'domain-1'); + expect(mockDomains.delete).toHaveBeenCalledWith('project-123', 'domain-1', 'main'); + }); + + it('should get domain via client', async () => { + const response = { id: 'domain-1' } as any; + mockDomains.get.mockResolvedValue(response); + const result = await environmentTask.getDomain('project-123', 'main', 'domain-1'); + expect(result).toBe(response); + expect(mockDomains.get).toHaveBeenCalledWith('project-123', 'domain-1', 'main'); + }); + + it('should list domains via client', async () => { + const response = [{ id: 'domain-1' }] as any; + mockDomains.list.mockResolvedValue(response); + const result = await environmentTask.listDomains('project-123', 'main'); + expect(result).toBe(response); + expect(mockDomains.list).toHaveBeenCalledWith('project-123', 'main'); + }); + + it('should update domain via client', async () => { + const response = { ok: true } as any; + mockDomains.update.mockResolvedValue(response); + const result = await environmentTask.updateDomain('project-123', 'main', 'domain-1', { + attributes: { env: 'true' }, + isDefault: true, + }); + expect(result).toBe(response); + expect(mockDomains.update).toHaveBeenCalledWith( + 'project-123', + 'domain-1', + { attributes: { env: 'true' }, isDefault: true }, + 'main', + ); + }); + }); + + describe('deployments', () => { + it('should require deploymentId', async () => { + await expect(environmentTask.getDeployment('project-123', 'main', '')).rejects.toThrow( + 'Deployment ID is required', + ); + }); + + it('should get deployment via API', async () => { + const response = { id: 'current' } as any; + mockDeploymentApi.getProjectsEnvironmentsDeployments.mockResolvedValue(response); + const result = await environmentTask.getDeployment('project-123', 'main', 'current'); + expect(result).toBe(response); + expect(mockDeploymentApi.getProjectsEnvironmentsDeployments).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + deploymentId: 'current', + }); + }); + + it('should list deployments via API', async () => { + const response = [{ id: 'current' }] as any; + mockDeploymentApi.listProjectsEnvironmentsDeployments.mockResolvedValue(response); + const result = await environmentTask.listDeployments('project-123', 'main'); + expect(result).toBe(response); + expect(mockDeploymentApi.listProjectsEnvironmentsDeployments).toHaveBeenCalledWith({ + projectId: 'project-123', + environmentId: 'main', + }); + }); + }); + + describe('logs/relationships', () => { + it('should throw not implemented for logs', async () => { + await expect(environmentTask.logs('project-123', 'main', 'app')).rejects.toThrow( + 'Not implemented yet', + ); + }); + + it('should return relationships for an app', async () => { + const relationships = { db: { host: 'db', port: 5432 } } as any; + mockClient.applications = { + configGet: jest.fn().mockResolvedValue({ relationships }), + } as any; + + const result = await environmentTask.relationships('project-123', 'main', 'app-1'); + expect(result).toEqual(relationships); + }); + }); +}); diff --git a/tests/unit/tasks/mount.test.ts b/tests/unit/tasks/mounts.test.ts similarity index 60% rename from tests/unit/tasks/mount.test.ts rename to tests/unit/tasks/mounts.test.ts index 50981de..a5a3604 100644 --- a/tests/unit/tasks/mount.test.ts +++ b/tests/unit/tasks/mounts.test.ts @@ -1,21 +1,28 @@ -import { MountTask } from '../../../src/core/tasks/mount.js'; +import { MountsTask } from '../../../src/core/tasks/mounts.js'; import { UpsunClient } from '../../../src/upsun.js'; // Mock the UpsunClient jest.mock('../../../src/upsun'); -describe('MountTask', () => { - let mountTask: MountTask; +describe('MountsTask', () => { + let mountTask: MountsTask; let mockClient: jest.Mocked; beforeEach(() => { mockClient = { apiConfig: { - basePath: 'https://api.upsun.com' - } + basePath: 'https://api.upsun.com', + }, + environments: { + getDeployment: jest.fn().mockResolvedValue({ + webapps: {}, + services: {}, + workers: {}, + }), + }, } as any; - - mountTask = new MountTask(mockClient); + + mountTask = new MountsTask(mockClient); }); afterEach(() => { @@ -29,7 +36,9 @@ describe('MountTask', () => { }); it('should throw "Cannot be implemented" error', async () => { - await expect(mountTask.download('project-123', 'mount-456')).rejects.toThrow('Cannot be implemented'); + await expect(mountTask.download('project-123', 'mount-456')).rejects.toThrow( + 'Cannot be implemented', + ); }); }); @@ -39,8 +48,9 @@ describe('MountTask', () => { expect(typeof mountTask.list).toBe('function'); }); - it('should throw "Cannot be implemented" error', async () => { - await expect(mountTask.list('project-123')).rejects.toThrow('Cannot be implemented'); + it('should list mounts from deployment', async () => { + const result = await mountTask.list('project-123'); + expect(result).toEqual({}); }); }); @@ -51,7 +61,9 @@ describe('MountTask', () => { }); it('should throw "Cannot be implemented" error', async () => { - await expect(mountTask.upload('project-123', 'mount-456')).rejects.toThrow('Cannot be implemented'); + await expect(mountTask.upload('project-123', 'mount-456', [])).rejects.toThrow( + 'Cannot be implemented', + ); }); }); }); diff --git a/tests/unit/tasks/operation.test.ts b/tests/unit/tasks/operation.test.ts deleted file mode 100644 index cc8645a..0000000 --- a/tests/unit/tasks/operation.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { OperationTask } from '../../../src/core/tasks/operation.js'; -import { UpsunClient } from '../../../src/upsun.js'; - -// Mock the UpsunClient -jest.mock('../../../src/upsun'); - -describe('OperationTask', () => { - let operationTask: OperationTask; - let mockClient: jest.Mocked; - - beforeEach(() => { - mockClient = { - apiConfig: { - basePath: 'https://api.upsun.com' - } - } as any; - - operationTask = new OperationTask(mockClient); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('constructor', () => { - it('should have OperationTask instance defined', () => { - expect(operationTask).toBeDefined(); - expect(operationTask).toBeInstanceOf(OperationTask); - }); - - it('should inherit from TaskBase', () => { - expect(operationTask).toHaveProperty('client'); - }); - }); -}); diff --git a/tests/unit/tasks/operations.test.ts b/tests/unit/tasks/operations.test.ts new file mode 100644 index 0000000..971c51c --- /dev/null +++ b/tests/unit/tasks/operations.test.ts @@ -0,0 +1,41 @@ +import { OperationsTask } from '../../../src/core/tasks/operations.js'; +import { UpsunClient } from '../../../src/upsun.js'; +import { RuntimeOperationsApi } from '../../../src/api/index.js'; + +// Mock the UpsunClient +jest.mock('../../../src/upsun'); + +describe('OperationsTask', () => { + let operationsTask: OperationsTask; + let mockClient: jest.Mocked; + let mockRuntimeOperationsApi: jest.Mocked; + + beforeEach(() => { + mockClient = { + apiConfig: { + basePath: 'https://api.upsun.com', + }, + } as any; + + mockRuntimeOperationsApi = { + runOperation: jest.fn(), + } as any; + + operationsTask = new OperationsTask(mockClient, mockRuntimeOperationsApi); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('constructor', () => { + it('should have OperationsTask instance defined', () => { + expect(operationsTask).toBeDefined(); + expect(operationsTask).toBeInstanceOf(OperationsTask); + }); + + it('should inherit from TaskBase', () => { + expect(operationsTask).toHaveProperty('client'); + }); + }); +}); diff --git a/tests/unit/tasks/organization.test.ts b/tests/unit/tasks/organizations.test.ts similarity index 51% rename from tests/unit/tasks/organization.test.ts rename to tests/unit/tasks/organizations.test.ts index 6ee6943..2868592 100644 --- a/tests/unit/tasks/organization.test.ts +++ b/tests/unit/tasks/organizations.test.ts @@ -1,44 +1,56 @@ -import { OrganizationTask } from '../../../src/core/tasks/organization.js'; +import { OrganizationsTask } from '../../../src/core/tasks/organizations.js'; import { UpsunClient } from '../../../src/upsun.js'; -import { OrganizationsApi } from '../../../src/apis-gen/index.js'; +import { OrganizationsApi } from '../../../src/api/index.js'; import nock from 'nock'; // Mock the UpsunClient and OrganizationsApi jest.mock('../../../src/upsun'); -jest.mock('../../../src/apis-gen/index.js'); +jest.mock('../../../src/api/index.js'); -describe('OrganizationTask', () => { - let organizationTask: OrganizationTask; +describe('OrganizationsTask', () => { + let organizationsTask: OrganizationsTask; let mockClient: jest.Mocked; let mockOrgApi: jest.Mocked; beforeEach(() => { // Mock OAuth2 authentication - nock('https://auth.upsun.com') - .post('/oauth2/token') - .reply(200, { - access_token: 'mock-access-token', - token_type: 'bearer', - expires_in: 3600 - }); + nock('https://auth.upsun.com').post('/oauth2/token').reply(200, { + access_token: 'mock-access-token', + token_type: 'bearer', + expires_in: 3600, + }); mockOrgApi = { getOrg: jest.fn(), createOrg: jest.fn(), listUserOrgs: jest.fn(), - deleteOrg: jest.fn() + deleteOrg: jest.fn(), } as any; - (OrganizationsApi as jest.MockedClass).mockImplementation(() => mockOrgApi); + (OrganizationsApi as jest.MockedClass).mockImplementation( + () => mockOrgApi, + ); mockClient = { apiConfig: { - basePath: 'https://api.upsun.com' + basePath: 'https://api.upsun.com', }, - getUserId: jest.fn().mockResolvedValue('user-123') + getUserId: jest.fn().mockResolvedValue('user-123'), } as any; - - organizationTask = new OrganizationTask(mockClient); + + organizationsTask = new OrganizationsTask( + mockClient, + mockOrgApi, + {} as any, + {} as any, + {} as any, + {} as any, + {} as any, + {} as any, + {} as any, + {} as any, + {} as any, + ); }); afterEach(() => { @@ -47,22 +59,22 @@ describe('OrganizationTask', () => { describe('list', () => { it('should have list method defined', () => { - expect(organizationTask.list).toBeDefined(); - expect(typeof organizationTask.list).toBe('function'); + expect(organizationsTask.list).toBeDefined(); + expect(typeof organizationsTask.list).toBe('function'); }); }); describe('info', () => { it('should have info method defined', () => { - expect(organizationTask.info).toBeDefined(); - expect(typeof organizationTask.info).toBe('function'); + expect(organizationsTask.info).toBeDefined(); + expect(typeof organizationsTask.info).toBe('function'); }); }); describe('create', () => { it('should have create method defined', () => { - expect(organizationTask.create).toBeDefined(); - expect(typeof organizationTask.create).toBe('function'); + expect(organizationsTask.create).toBeDefined(); + expect(typeof organizationsTask.create).toBe('function'); }); }); @@ -73,12 +85,12 @@ describe('OrganizationTask', () => { name: 'Test Organization', description: 'A test organization', created_at: '2023-01-01T00:00:00Z', - updated_at: '2023-01-02T00:00:00Z' + updated_at: '2023-01-02T00:00:00Z', }; mockOrgApi.getOrg.mockResolvedValue(mockOrganization); - const result = await organizationTask.info('org-123'); + const result = await organizationsTask.info('org-123'); expect(result).toEqual(mockOrganization); expect(mockOrgApi.getOrg).toHaveBeenCalledWith({ organizationId: 'org-123' }); }); @@ -86,7 +98,9 @@ describe('OrganizationTask', () => { it('should handle info errors for non-existent organization', async () => { mockOrgApi.getOrg.mockRejectedValue(new Error('Organization not found')); - await expect(organizationTask.info('non-existent')).rejects.toThrow('Organization not found'); + await expect(organizationsTask.info('non-existent')).rejects.toThrow( + 'Organization not found', + ); }); }); @@ -95,34 +109,36 @@ describe('OrganizationTask', () => { const mockOrganization = { id: 'org-123', name: 'Test Organization', - created_at: '2023-01-01T00:00:00Z' + created_at: '2023-01-01T00:00:00Z', }; mockOrgApi.createOrg.mockResolvedValue(mockOrganization); - const result = await organizationTask.create('Test Organization'); + const result = await organizationsTask.create('Test Organization'); expect(result).toEqual(mockOrganization); - expect(mockOrgApi.createOrg).toHaveBeenCalledWith({ - createOrgRequest: { - ownerId: undefined, - name: undefined, - label: 'Test Organization', - country: undefined - } + expect(mockOrgApi.createOrg).toHaveBeenCalledWith({ + createOrgRequest: { + ownerId: undefined, + name: undefined, + label: 'Test Organization', + country: undefined, + }, }); }); it('should handle creation errors', async () => { mockOrgApi.createOrg.mockRejectedValue(new Error('Invalid organization name')); - await expect(organizationTask.create('Invalid Name')).rejects.toThrow('Invalid organization name'); + await expect(organizationsTask.create('Invalid Name')).rejects.toThrow( + 'Invalid organization name', + ); }); }); describe('delete', () => { it('should have delete method defined', () => { - expect(organizationTask.delete).toBeDefined(); - expect(typeof organizationTask.delete).toBe('function'); + expect(organizationsTask.delete).toBeDefined(); + expect(typeof organizationsTask.delete).toBe('function'); }); }); }); diff --git a/tests/unit/tasks/project.test.ts b/tests/unit/tasks/project.test.ts deleted file mode 100644 index 3990010..0000000 --- a/tests/unit/tasks/project.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { ProjectTask } from '../../../src/core/tasks/project.js'; -import { UpsunClient } from '../../../src/upsun.js'; -import nock from 'nock'; - -// Mock the UpsunClient -jest.mock('../../../src/upsun'); - -describe('ProjectTask', () => { - let projectTask: ProjectTask; - let mockClient: jest.Mocked; - - beforeEach(() => { - mockClient = { - apiConfig: { - basePath: 'https://api.upsun.com' - } - } as any; - - projectTask = new ProjectTask(mockClient); - }); - - afterEach(() => { - nock.cleanAll(); - }); - - describe('info', () => { - it('should get project information', async () => { - expect(projectTask.info).toBeDefined(); - expect(typeof projectTask.info).toBe('function'); - }); - }); - - describe('list', () => { - it('should list organization subscriptions', async () => { - expect(projectTask.list).toBeDefined(); - expect(typeof projectTask.list).toBe('function'); - }); - }); - - describe('delete', () => { - it('should delete a project', async () => { - expect(projectTask.delete).toBeDefined(); - expect(typeof projectTask.delete).toBe('function'); - }); - }); - - describe('clearBuildCache', () => { - it('should clear project build cache', async () => { - expect(projectTask.clearBuildCache).toBeDefined(); - expect(typeof projectTask.clearBuildCache).toBe('function'); - }); - }); - - describe('create', () => { - it('should have create method defined', () => { - expect(projectTask.create).toBeDefined(); - expect(typeof projectTask.create).toBe('function'); - }); - }); - - describe('get', () => { - it('should have get method defined', () => { - expect(projectTask.get).toBeDefined(); - expect(typeof projectTask.get).toBe('function'); - }); - }); -}); diff --git a/tests/unit/tasks/projects.test.ts b/tests/unit/tasks/projects.test.ts new file mode 100644 index 0000000..00c4137 --- /dev/null +++ b/tests/unit/tasks/projects.test.ts @@ -0,0 +1,67 @@ +import { ProjectsTask } from '../../../src/core/tasks/projects.js'; +import { UpsunClient } from '../../../src/upsun.js'; +import nock from 'nock'; + +// Mock the UpsunClient +jest.mock('../../../src/upsun'); + +describe('ProjectsTask', () => { + let projectsTask: ProjectsTask; + let mockClient: jest.Mocked; + + beforeEach(() => { + mockClient = { + apiConfig: { + basePath: 'https://api.upsun.com', + }, + } as any; + + projectsTask = new ProjectsTask(mockClient, {} as any, {} as any, {} as any, {} as any); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + describe('info', () => { + it('should get project information', async () => { + expect(projectsTask.info).toBeDefined(); + expect(typeof projectsTask.info).toBe('function'); + }); + }); + + describe('list', () => { + it('should list organization subscriptions', async () => { + expect(projectsTask.list).toBeDefined(); + expect(typeof projectsTask.list).toBe('function'); + }); + }); + + describe('delete', () => { + it('should delete a project', async () => { + expect(projectsTask.delete).toBeDefined(); + expect(typeof projectsTask.delete).toBe('function'); + }); + }); + + describe('clearBuildCache', () => { + it('should clear project build cache', async () => { + expect(projectsTask.clearBuildCache).toBeDefined(); + expect(typeof projectsTask.clearBuildCache).toBe('function'); + }); + }); + + describe('create', () => { + it('should have create method defined', () => { + expect(projectsTask.create).toBeDefined(); + expect(typeof projectsTask.create).toBe('function'); + }); + }); + + describe('get', () => { + it('should have get method defined', () => { + expect(projectsTask.get).toBeDefined(); + expect(typeof projectsTask.get).toBe('function'); + }); + }); +}); diff --git a/tests/unit/tasks/route.test.ts b/tests/unit/tasks/routes.test.ts similarity index 75% rename from tests/unit/tasks/route.test.ts rename to tests/unit/tasks/routes.test.ts index 7ba8cdf..9c9700d 100644 --- a/tests/unit/tasks/route.test.ts +++ b/tests/unit/tasks/routes.test.ts @@ -1,31 +1,31 @@ -import { RouteTask } from '../../../src/core/tasks/route.js'; +import { RoutesTask } from '../../../src/core/tasks/routes.js'; import { UpsunClient } from '../../../src/upsun.js'; -import { RoutingApi } from '../../../src/apis-gen/index.js'; +import { RoutingApi } from '../../../src/api/index.js'; // Mock the UpsunClient and RoutingApi jest.mock('../../../src/upsun'); -jest.mock('../../../src/apis-gen/index.js'); +jest.mock('../../../src/api/index.js'); -describe('RouteTask', () => { - let routeTask: RouteTask; +describe('RoutesTask', () => { + let routesTask: RoutesTask; let mockClient: jest.Mocked; let mockRoutingApi: jest.Mocked; beforeEach(() => { mockRoutingApi = { getProjectsEnvironmentsRoutes: jest.fn(), - listProjectsEnvironmentsRoutes: jest.fn() + listProjectsEnvironmentsRoutes: jest.fn(), } as any; (RoutingApi as jest.MockedClass).mockImplementation(() => mockRoutingApi); mockClient = { apiConfig: { - basePath: 'https://api.upsun.com' - } + basePath: 'https://api.upsun.com', + }, } as any; - - routeTask = new RouteTask(mockClient); + + routesTask = new RoutesTask(mockClient, mockRoutingApi); }); afterEach(() => { @@ -44,34 +44,34 @@ describe('RouteTask', () => { strictTransportSecurity: null, minVersion: null, clientAuthentication: null, - clientCertificateAuthorities: [] + clientCertificateAuthorities: [], }, cache: { enabled: true, defaultTtl: 300, headers: [], - cookies: [] + cookies: [], }, ssi: { - enabled: false + enabled: false, }, upstream: 'app:http', redirects: { expires: null, - paths: {} - } + paths: {}, + }, }; mockRoutingApi.getProjectsEnvironmentsRoutes.mockResolvedValue(mockRoute as any); - const result = await routeTask.get('project-123', 'main', 'route-123'); + const result = await routesTask.get('project-123', 'main', 'route-123'); expect(result).toBeDefined(); expect(result.id).toBe('route-123'); expect(result.type).toBe('upstream'); expect(mockRoutingApi.getProjectsEnvironmentsRoutes).toHaveBeenCalledWith({ projectId: 'project-123', environmentId: 'main', - routeId: 'route-123' + routeId: 'route-123', }); // Type-safe check for upstream property if (result.type === 'upstream') { @@ -82,7 +82,9 @@ describe('RouteTask', () => { it('should handle get errors for non-existent route', async () => { mockRoutingApi.getProjectsEnvironmentsRoutes.mockRejectedValue(new Error('Route not found')); - await expect(routeTask.get('project-123', 'main', 'non-existent')).rejects.toThrow('Route not found'); + await expect(routesTask.get('project-123', 'main', 'non-existent')).rejects.toThrow( + 'Route not found', + ); }); }); @@ -99,22 +101,22 @@ describe('RouteTask', () => { strictTransportSecurity: null, minVersion: null, clientAuthentication: null, - clientCertificateAuthorities: [] + clientCertificateAuthorities: [], }, cache: { enabled: false, defaultTtl: 0, headers: [], - cookies: [] + cookies: [], }, ssi: { - enabled: false + enabled: false, }, upstream: 'app:http', redirects: { expires: null, - paths: {} - } + paths: {}, + }, }, { primary: false, @@ -126,41 +128,41 @@ describe('RouteTask', () => { strictTransportSecurity: null, minVersion: null, clientAuthentication: null, - clientCertificateAuthorities: [] + clientCertificateAuthorities: [], }, cache: { enabled: false, defaultTtl: 0, headers: [], - cookies: [] + cookies: [], }, ssi: { - enabled: false + enabled: false, }, upstream: 'api:http', redirects: { expires: null, - paths: {} - } - } + paths: {}, + }, + }, ]; mockRoutingApi.listProjectsEnvironmentsRoutes.mockResolvedValue(mockRoutes as any); - const result = await routeTask.list('project-123', 'main'); + const result = await routesTask.list('project-123', 'main'); expect(result).toHaveLength(2); expect(result[0].id).toBe('route-1'); expect(result[1].id).toBe('route-2'); expect(mockRoutingApi.listProjectsEnvironmentsRoutes).toHaveBeenCalledWith({ projectId: 'project-123', - environmentId: 'main' + environmentId: 'main', }); }); it('should handle empty route list', async () => { mockRoutingApi.listProjectsEnvironmentsRoutes.mockResolvedValue([]); - const result = await routeTask.list('project-123', 'main'); + const result = await routesTask.list('project-123', 'main'); expect(result).toEqual([]); }); }); diff --git a/tests/unit/tasks/service.test.ts b/tests/unit/tasks/services.test.ts similarity index 65% rename from tests/unit/tasks/service.test.ts rename to tests/unit/tasks/services.test.ts index 4e6c683..031f2d7 100644 --- a/tests/unit/tasks/service.test.ts +++ b/tests/unit/tasks/services.test.ts @@ -1,21 +1,21 @@ -import { ServiceTask } from '../../../src/core/tasks/service.js'; +import { ServicesTask } from '../../../src/core/tasks/services.js'; import { UpsunClient } from '../../../src/upsun.js'; // Mock the UpsunClient jest.mock('../../../src/upsun'); -describe('ServiceTask', () => { - let serviceTask: ServiceTask; +describe('ServicesTask', () => { + let serviceTask: ServicesTask; let mockClient: jest.Mocked; beforeEach(() => { mockClient = { apiConfig: { - basePath: 'https://api.upsun.com' - } + basePath: 'https://api.upsun.com', + }, } as any; - - serviceTask = new ServiceTask(mockClient); + + serviceTask = new ServicesTask(mockClient); }); afterEach(() => { @@ -25,7 +25,7 @@ describe('ServiceTask', () => { describe('constructor', () => { it('should have ServiceTask instance defined', () => { expect(serviceTask).toBeDefined(); - expect(serviceTask).toBeInstanceOf(ServiceTask); + expect(serviceTask).toBeInstanceOf(ServicesTask); }); it('should inherit from TaskBase', () => { diff --git a/tests/unit/tasks/source-operation.test.ts b/tests/unit/tasks/source-operations.test.ts similarity index 52% rename from tests/unit/tasks/source-operation.test.ts rename to tests/unit/tasks/source-operations.test.ts index 026e147..6b768ea 100644 --- a/tests/unit/tasks/source-operation.test.ts +++ b/tests/unit/tasks/source-operations.test.ts @@ -1,21 +1,28 @@ -import { SourceOperationTask } from '../../../src/core/tasks/source-operation.js'; +import { SourceOperationsTask } from '../../../src/core/tasks/source-operations.js'; import { UpsunClient } from '../../../src/upsun.js'; // Mock the UpsunClient jest.mock('../../../src/upsun'); -describe('SourceOperationTask', () => { - let sourceOperationTask: SourceOperationTask; +describe('SourceOperationsTask', () => { + let sourceOperationTask: SourceOperationsTask; let mockClient: jest.Mocked; + let mockSourceOperationsApi: any; beforeEach(() => { + mockSourceOperationsApi = { + listProjectsEnvironmentsSourceOperations: jest.fn(), + getProjectsEnvironmentsSourceOperations: jest.fn(), + actionProjectsEnvironmentsSourceOperations: jest.fn(), + }; + mockClient = { apiConfig: { - basePath: 'https://api.upsun.com' - } + basePath: 'https://api.upsun.com', + }, } as any; - - sourceOperationTask = new SourceOperationTask(mockClient); + + sourceOperationTask = new SourceOperationsTask(mockClient, mockSourceOperationsApi); }); afterEach(() => { @@ -25,7 +32,7 @@ describe('SourceOperationTask', () => { describe('constructor', () => { it('should have SourceOperationTask instance defined', () => { expect(sourceOperationTask).toBeDefined(); - expect(sourceOperationTask).toBeInstanceOf(SourceOperationTask); + expect(sourceOperationTask).toBeInstanceOf(SourceOperationsTask); }); it('should inherit from TaskBase', () => { diff --git a/tests/unit/tasks/ssh.test.ts b/tests/unit/tasks/ssh.test.ts index 173e418..8719cda 100644 --- a/tests/unit/tasks/ssh.test.ts +++ b/tests/unit/tasks/ssh.test.ts @@ -1,30 +1,31 @@ import { SshTask } from '../../../src/core/tasks/ssh.js'; import { UpsunClient } from '../../../src/upsun.js'; -import { SSHKeysApi } from '../../../src/apis-gen/index.js'; +import { SshKeysApi } from '../../../src/api/index.js'; // Mock the UpsunClient and SSHKeysApi jest.mock('../../../src/upsun'); -jest.mock('../../../src/apis-gen/index.js'); +jest.mock('../../../src/api/index.js'); describe('SshTask', () => { let sshTask: SshTask; let mockClient: jest.Mocked; - let mockSshApi: jest.Mocked; + let mockSshApi: jest.Mocked; beforeEach(() => { mockSshApi = { - createSshKey: jest.fn() + createSshKey: jest.fn(), + deleteSshKey: jest.fn(), } as any; - (SSHKeysApi as jest.MockedClass).mockImplementation(() => mockSshApi); + (SshKeysApi as jest.MockedClass).mockImplementation(() => mockSshApi); mockClient = { apiConfig: { - basePath: 'https://api.upsun.com' - } + basePath: 'https://api.upsun.com', + }, } as any; - - sshTask = new SshTask(mockClient); + + sshTask = new SshTask(mockClient, mockSshApi); }); afterEach(() => { @@ -42,38 +43,32 @@ describe('SshTask', () => { id: 'key-123', title: 'test-key', value: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...', - created_at: '2023-01-01T00:00:00Z' + created_at: '2023-01-01T00:00:00Z', }; mockSshApi.createSshKey.mockResolvedValue(mockSshKey as any); - const result = await sshTask.add('user-456', 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...', 'test-key'); + const result = await sshTask.add( + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...', + 'user-456', + 'test-key', + ); expect(result).toBeDefined(); expect(mockSshApi.createSshKey).toHaveBeenCalledWith({ createSshKeyRequest: { uuid: 'user-456', value: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...', - title: 'test-key' - } + title: 'test-key', + }, }); }); it('should handle SSH key addition errors', async () => { mockSshApi.createSshKey.mockRejectedValue(new Error('SSH key already exists')); - await expect(sshTask.add('user-456', 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...', 'test-key')) - .rejects.toThrow('SSH key already exists'); - }); - }); - - describe('list', () => { - it('should have list method defined', () => { - expect(sshTask.list).toBeDefined(); - expect(typeof sshTask.list).toBe('function'); - }); - - it('should throw "Method not implemented" error', () => { - expect(() => sshTask.list('user-456')).toThrow('Method not implemented.'); + await expect( + sshTask.add('ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...', 'user-456', 'test-key'), + ).rejects.toThrow('SSH key already exists'); }); }); @@ -83,8 +78,11 @@ describe('SshTask', () => { expect(typeof sshTask.delete).toBe('function'); }); - it('should throw "Method not implemented" error', () => { - expect(() => sshTask.delete('user-456', 'key-123')).toThrow('Method not implemented.'); + it('should delete an SSH key', async () => { + mockSshApi.deleteSshKey.mockResolvedValue(undefined as any); + + await sshTask.delete(123); + expect(mockSshApi.deleteSshKey).toHaveBeenCalledWith({ keyId: 123 }); }); }); }); diff --git a/tests/unit/tasks/team.test.ts b/tests/unit/tasks/team.test.ts deleted file mode 100644 index 534cada..0000000 --- a/tests/unit/tasks/team.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { TeamTask } from '../../../src/core/tasks/team.js'; -import { UpsunClient } from '../../../src/upsun.js'; - -// Mock the UpsunClient -jest.mock('../../../src/upsun'); - -describe('TeamTask', () => { - let teamTask: TeamTask; - let mockClient: jest.Mocked; - - beforeEach(() => { - mockClient = { - apiConfig: { - basePath: 'https://api.upsun.com' - } - } as any; - - teamTask = new TeamTask(mockClient); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('constructor', () => { - it('should have TeamTask instance defined', () => { - expect(teamTask).toBeDefined(); - expect(teamTask).toBeInstanceOf(TeamTask); - }); - - it('should inherit from TaskBase', () => { - expect(teamTask).toHaveProperty('client'); - }); - }); -}); diff --git a/tests/unit/tasks/teams.test.ts b/tests/unit/tasks/teams.test.ts new file mode 100644 index 0000000..8cabbd2 --- /dev/null +++ b/tests/unit/tasks/teams.test.ts @@ -0,0 +1,38 @@ +import { TeamsTask } from '../../../src/core/tasks/teams.js'; +import { UpsunClient } from '../../../src/upsun.js'; + +// Mock the UpsunClient +jest.mock('../../../src/upsun'); + +describe('TeamsTask', () => { + let teamsTask: TeamsTask; + let mockClient: jest.Mocked; + + beforeEach(() => { + mockClient = { + apiConfig: { + basePath: 'https://api.upsun.com', + }, + } as any; + + const mockTeamsApi = {} as any; + const mockTeamAccessApi = {} as any; + + teamsTask = new TeamsTask(mockClient, mockTeamsApi, mockTeamAccessApi); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('constructor', () => { + it('should have TeamTask instance defined', () => { + expect(teamsTask).toBeDefined(); + expect(teamsTask).toBeInstanceOf(TeamsTask); + }); + + it('should inherit from TaskBase', () => { + expect(teamsTask).toHaveProperty('client'); + }); + }); +}); diff --git a/tests/unit/tasks/user.test.ts b/tests/unit/tasks/users.test.ts similarity index 56% rename from tests/unit/tasks/user.test.ts rename to tests/unit/tasks/users.test.ts index f782163..483e6eb 100644 --- a/tests/unit/tasks/user.test.ts +++ b/tests/unit/tasks/users.test.ts @@ -1,30 +1,40 @@ -import { UserTask } from '../../../src/core/tasks/user.js'; +import { UsersTask } from '../../../src/core/tasks/users.js'; import { UpsunClient } from '../../../src/upsun.js'; -import { UsersApi } from '../../../src/apis-gen/index.js'; +import { UsersApi } from '../../../src/api/index.js'; // Mock the UpsunClient and UsersApi -jest.mock('../../../src/upsun'); -jest.mock('../../../src/apis-gen/index.js'); +jest.mock('../../../src/upsun.js'); +jest.mock('../../../src/api/index.js'); -describe('UserTask', () => { - let userTask: UserTask; +describe('UsersTask', () => { + let usersTask: UsersTask; let mockClient: jest.Mocked; let mockUsersApi: jest.Mocked; beforeEach(() => { mockUsersApi = { - getCurrentUser: jest.fn() + getCurrentUser: jest.fn(), } as any; (UsersApi as jest.MockedClass).mockImplementation(() => mockUsersApi); mockClient = { apiConfig: { - basePath: 'https://api.upsun.com' - } + basePath: 'https://api.upsun.com', + }, } as any; - - userTask = new UserTask(mockClient); + + usersTask = new UsersTask( + mockClient, + mockUsersApi, + {} as any, // userProfilesApi + {} as any, // userAccessApi + {} as any, // apiTokensApi + {} as any, // connectionsApi + {} as any, // grantsApi + {} as any, // mfaApi + {} as any, // phoneNumberApi + ); }); afterEach(() => { @@ -33,8 +43,8 @@ describe('UserTask', () => { describe('me', () => { it('should have me method defined', () => { - expect(userTask.me).toBeDefined(); - expect(typeof userTask.me).toBe('function'); + expect(usersTask.me).toBeDefined(); + expect(typeof usersTask.me).toBe('function'); }); it('should get current user information', async () => { @@ -42,12 +52,12 @@ describe('UserTask', () => { id: 'user-123', email: 'test@example.com', name: 'Test User', - created_at: '2023-01-01T00:00:00Z' + created_at: '2023-01-01T00:00:00Z', }; mockUsersApi.getCurrentUser.mockResolvedValue(mockUser as any); - const result = await userTask.me(); + const result = await usersTask.me(); expect(result).toBeDefined(); expect((result as any).id).toBe('user-123'); expect((result as any).email).toBe('test@example.com'); @@ -57,7 +67,7 @@ describe('UserTask', () => { it('should handle authentication errors', async () => { mockUsersApi.getCurrentUser.mockRejectedValue(new Error('Unauthorized')); - await expect(userTask.me()).rejects.toThrow('Unauthorized'); + await expect(usersTask.me()).rejects.toThrow('Unauthorized'); }); }); }); diff --git a/tests/unit/tasks/variable.test.ts b/tests/unit/tasks/variable.test.ts deleted file mode 100644 index f560f88..0000000 --- a/tests/unit/tasks/variable.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { VariableTask } from '../../../src/core/tasks/variable'; -import { UpsunClient } from '../../../src/upsun'; - -// Mock the UpsunClient -jest.mock('../../../src/upsun'); - -describe('VariableTask', () => { - let variableTask: VariableTask; - let mockClient: jest.Mocked; - - beforeEach(() => { - mockClient = { - apiConfig: { - basePath: 'https://api.upsun.com' - } - } as any; - - variableTask = new VariableTask(mockClient); - }); - - describe('constructor', () => { - it('should initialize properly', () => { - expect(variableTask).toBeDefined(); - expect(variableTask).toBeInstanceOf(VariableTask); - }); - }); - - // Note: VariableTask currently has no implemented methods - // Tests will be added when methods are implemented -}); diff --git a/tests/unit/tasks/variables.test.ts b/tests/unit/tasks/variables.test.ts new file mode 100644 index 0000000..0f472e6 --- /dev/null +++ b/tests/unit/tasks/variables.test.ts @@ -0,0 +1,364 @@ +import { VariablesTask } from '../../../src/core/tasks/variables.js'; +import { ProjectVariablesApi } from '../../../src/api/ProjectVariablesApi.js'; +import { EnvironmentVariablesApi } from '../../../src/index.js'; +import { UpsunClient } from '../../../src/upsun'; + +// Mock the UpsunClient +jest.mock('../../../src/upsun'); +jest.mock('../../../src/api/ProjectVariablesApi.js'); +jest.mock('../../../src/index.js', () => { + const actual = jest.requireActual('../../../src/index.js'); + return { + ...actual, + EnvironmentVariablesApi: jest.fn(), + }; +}); + +describe('VariablesTask', () => { + let variablesTask: VariablesTask; + let mockClient: jest.Mocked; + let mockProjVarApi: jest.Mocked; + let mockEnvVarApi: jest.Mocked; + + beforeEach(() => { + mockProjVarApi = { + createProjectsVariables: jest.fn(), + deleteProjectsVariables: jest.fn(), + getProjectsVariables: jest.fn(), + listProjectsVariables: jest.fn(), + updateProjectsVariables: jest.fn(), + } as any; + + mockEnvVarApi = { + createProjectsEnvironmentsVariables: jest.fn(), + deleteProjectsEnvironmentsVariables: jest.fn(), + getProjectsEnvironmentsVariables: jest.fn(), + listProjectsEnvironmentsVariables: jest.fn(), + updateProjectsEnvironmentsVariables: jest.fn(), + } as any; + + (ProjectVariablesApi as jest.MockedClass).mockImplementation( + () => mockProjVarApi, + ); + ( + EnvironmentVariablesApi as jest.MockedClass + ).mockImplementation(() => mockEnvVarApi); + + mockClient = { + apiConfig: { + basePath: 'https://api.upsun.com', + }, + } as any; + + variablesTask = new VariablesTask(mockClient, mockProjVarApi, mockEnvVarApi); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('constructor', () => { + it('should initialize properly', () => { + expect(variablesTask).toBeDefined(); + expect(variablesTask).toBeInstanceOf(VariablesTask); + }); + }); + + describe('createProjectVariable', () => { + it('should require projectId', async () => { + await expect(variablesTask.createProjectVariable('', 'NAME', 'VALUE')).rejects.toThrow( + 'Project ID is required', + ); + }); + + it('should require name', async () => { + await expect(variablesTask.createProjectVariable('prj-1', '', 'VALUE')).rejects.toThrow( + 'Variable name is required', + ); + }); + + it('should require value', async () => { + await expect(variablesTask.createProjectVariable('prj-1', 'NAME', '')).rejects.toThrow( + 'Variable value is required', + ); + }); + + it('should call api with create payload', async () => { + const response = { ok: true } as any; + mockProjVarApi.createProjectsVariables.mockResolvedValue(response); + + const result = await variablesTask.createProjectVariable('prj-1', 'NAME', 'VALUE', { + attributes: { env: 'true' }, + isJson: true, + isSensitive: false, + visibleBuild: true, + visibleRuntime: false, + applicationScope: ['app'], + }); + + expect(result).toBe(response); + expect(mockProjVarApi.createProjectsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + projectVariableCreateInput: { + name: 'NAME', + value: 'VALUE', + attributes: { env: 'true' }, + isJson: true, + isSensitive: false, + visibleBuild: true, + visibleRuntime: false, + applicationScope: ['app'], + }, + }); + }); + }); + + describe('deleteProjectVariable', () => { + it('should require variableId', async () => { + await expect(variablesTask.deleteProjectVariable('prj-1', '')).rejects.toThrow( + 'Variable ID is required', + ); + }); + + it('should call api with delete payload', async () => { + await variablesTask.deleteProjectVariable('prj-1', 'var-1'); + expect(mockProjVarApi.deleteProjectsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + projectVariableId: 'var-1', + }); + }); + }); + + describe('getProjectVariable', () => { + it('should require variableId', async () => { + await expect(variablesTask.getProjectVariable('prj-1', '')).rejects.toThrow( + 'Variable ID is required', + ); + }); + + it('should call api with get payload', async () => { + const response = { id: 'var-1', name: 'NAME' } as any; + mockProjVarApi.getProjectsVariables.mockResolvedValue(response); + + const result = await variablesTask.getProjectVariable('prj-1', 'var-1'); + expect(result).toBe(response); + expect(mockProjVarApi.getProjectsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + projectVariableId: 'var-1', + }); + }); + }); + + describe('listProjectVariables', () => { + it('should call api with list payload', async () => { + const response = [{ id: 'var-1' }] as any; + mockProjVarApi.listProjectsVariables.mockResolvedValue(response); + + const result = await variablesTask.listProjectVariables('prj-1'); + expect(result).toBe(response); + expect(mockProjVarApi.listProjectsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + }); + }); + }); + + describe('updateProjectVariable', () => { + it('should require variableId', async () => { + await expect(variablesTask.updateProjectVariable('prj-1', '')).rejects.toThrow( + 'Variable ID is required', + ); + }); + + it('should call api with update payload', async () => { + const response = { ok: true } as any; + mockProjVarApi.updateProjectsVariables.mockResolvedValue(response); + + const result = await variablesTask.updateProjectVariable('prj-1', 'var-1', { + name: 'NAME', + value: 'VALUE', + attributes: { env: 'true' }, + isJson: true, + isSensitive: true, + visibleBuild: false, + visibleRuntime: true, + applicationScope: ['app'], + }); + + expect(result).toBe(response); + expect(mockProjVarApi.updateProjectsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + projectVariableId: 'var-1', + projectVariablePatch: { + name: 'NAME', + value: 'VALUE', + attributes: { env: 'true' }, + isJson: true, + isSensitive: true, + visibleBuild: false, + visibleRuntime: true, + applicationScope: ['app'], + }, + }); + }); + }); + + describe('createEnvironmentVariable', () => { + it('should require projectId', async () => { + await expect( + variablesTask.createEnvironmentVariable('', 'env-1', 'NAME', 'VALUE'), + ).rejects.toThrow('Project ID is required'); + }); + + it('should require environmentId', async () => { + await expect( + variablesTask.createEnvironmentVariable('prj-1', '', 'NAME', 'VALUE'), + ).rejects.toThrow('Environment ID is required'); + }); + + it('should require name', async () => { + await expect( + variablesTask.createEnvironmentVariable('prj-1', 'env-1', '', 'VALUE'), + ).rejects.toThrow('Variable name is required'); + }); + + it('should require value', async () => { + await expect( + variablesTask.createEnvironmentVariable('prj-1', 'env-1', 'NAME', ''), + ).rejects.toThrow('Variable value is required'); + }); + + it('should call api with create payload', async () => { + const response = { ok: true } as any; + mockEnvVarApi.createProjectsEnvironmentsVariables.mockResolvedValue(response); + + const result = await variablesTask.createEnvironmentVariable( + 'prj-1', + 'env-1', + 'NAME', + 'VALUE', + { + attributes: { env: 'true' }, + isJson: true, + isSensitive: false, + visibleBuild: true, + visibleRuntime: false, + applicationScope: ['app'], + }, + ); + + expect(result).toBe(response); + expect(mockEnvVarApi.createProjectsEnvironmentsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + environmentId: 'env-1', + environmentVariableCreateInput: { + name: 'NAME', + value: 'VALUE', + attributes: { env: 'true' }, + isJson: true, + isSensitive: false, + visibleBuild: true, + visibleRuntime: false, + applicationScope: ['app'], + }, + }); + }); + }); + + describe('deleteEnvironmentVariable', () => { + it('should require variableId', async () => { + await expect(variablesTask.deleteEnvironmentVariable('prj-1', 'env-1', '')).rejects.toThrow( + 'Variable ID is required', + ); + }); + + it('should call api with delete payload', async () => { + await variablesTask.deleteEnvironmentVariable('prj-1', 'env-1', 'var-1'); + expect(mockEnvVarApi.deleteProjectsEnvironmentsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + environmentId: 'env-1', + variableId: 'var-1', + }); + }); + }); + + describe('getEnvironmentVariable', () => { + it('should require variableId', async () => { + await expect(variablesTask.getEnvironmentVariable('prj-1', 'env-1', '')).rejects.toThrow( + 'Variable ID is required', + ); + }); + + it('should call api with get payload', async () => { + const response = { id: 'var-1', name: 'NAME' } as any; + mockEnvVarApi.getProjectsEnvironmentsVariables.mockResolvedValue(response); + + const result = await variablesTask.getEnvironmentVariable('prj-1', 'env-1', 'var-1'); + expect(result).toBe(response); + expect(mockEnvVarApi.getProjectsEnvironmentsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + environmentId: 'env-1', + variableId: 'var-1', + }); + }); + }); + + describe('listEnvironmentVariables', () => { + it('should call api with list payload', async () => { + const response = [{ id: 'var-1' }] as any; + mockEnvVarApi.listProjectsEnvironmentsVariables.mockResolvedValue(response); + + const result = await variablesTask.listEnvironmentVariables('prj-1', 'env-1'); + expect(result).toBe(response); + expect(mockEnvVarApi.listProjectsEnvironmentsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + environmentId: 'env-1', + }); + }); + }); + + describe('updateEnvironmentVariable', () => { + it('should require variableId', async () => { + await expect( + variablesTask.updateEnvironmentVariable('prj-1', 'env-1', '', 'NAME', 'VALUE'), + ).rejects.toThrow('Variable ID is required'); + }); + + it('should call api with update payload', async () => { + const response = { ok: true } as any; + mockEnvVarApi.updateProjectsEnvironmentsVariables.mockResolvedValue(response); + + const result = await variablesTask.updateEnvironmentVariable( + 'prj-1', + 'env-1', + 'var-1', + 'NAME', + 'VALUE', + { + attributes: { env: 'true' }, + isJson: true, + isSensitive: true, + visibleBuild: false, + visibleRuntime: true, + applicationScope: ['app'], + }, + ); + + expect(result).toBe(response); + expect(mockEnvVarApi.updateProjectsEnvironmentsVariables).toHaveBeenCalledWith({ + projectId: 'prj-1', + environmentId: 'env-1', + variableId: 'var-1', + environmentVariablePatch: { + name: 'NAME', + value: 'VALUE', + attributes: { env: 'true' }, + isJson: true, + isSensitive: true, + visibleBuild: false, + visibleRuntime: true, + applicationScope: ['app'], + }, + }); + }); + }); +}); diff --git a/tests/unit/tasks/worker.test.ts b/tests/unit/tasks/worker.test.ts deleted file mode 100644 index 07f1de9..0000000 --- a/tests/unit/tasks/worker.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { WorkerTask } from '../../../src/core/tasks/worker.js'; -import { UpsunClient } from '../../../src/upsun.js'; - -// Mock the UpsunClient -jest.mock('../../../src/upsun'); - -describe('WorkerTask', () => { - let workerTask: WorkerTask; - let mockClient: jest.Mocked; - - beforeEach(() => { - mockClient = { - apiConfig: { - basePath: 'https://api.upsun.com' - } - } as any; - - workerTask = new WorkerTask(mockClient); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('constructor', () => { - it('should have WorkerTask instance defined', () => { - expect(workerTask).toBeDefined(); - expect(workerTask).toBeInstanceOf(WorkerTask); - }); - - it('should inherit from TaskBase', () => { - expect(workerTask).toHaveProperty('client'); - }); - }); -}); diff --git a/tests/unit/tasks/workers.test.ts b/tests/unit/tasks/workers.test.ts new file mode 100644 index 0000000..3f08f41 --- /dev/null +++ b/tests/unit/tasks/workers.test.ts @@ -0,0 +1,35 @@ +import { WorkersTask } from '../../../src/core/tasks/workers.js'; +import { UpsunClient } from '../../../src/upsun.js'; + +// Mock the UpsunClient +jest.mock('../../../src/upsun'); + +describe('WorkersTask', () => { + let workersTask: WorkersTask; + let mockClient: jest.Mocked; + + beforeEach(() => { + mockClient = { + apiConfig: { + basePath: 'https://api.upsun.com', + }, + } as any; + + workersTask = new WorkersTask(mockClient); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('constructor', () => { + it('should have WorkersTask instance defined', () => { + expect(workersTask).toBeDefined(); + expect(workersTask).toBeInstanceOf(WorkersTask); + }); + + it('should inherit from TaskBase', () => { + expect(workersTask).toHaveProperty('client'); + }); + }); +}); diff --git a/tests/unit/upsun-client.test.ts b/tests/unit/upsun-client.test.ts index 93eb670..e826810 100644 --- a/tests/unit/upsun-client.test.ts +++ b/tests/unit/upsun-client.test.ts @@ -3,11 +3,11 @@ import nock from 'nock'; describe('UpsunClient', () => { let client: UpsunClient; - + beforeEach(() => { const config: UpsunConfig = { ...DEFAULT_UPSUN_CONFIG, - apiKey: 'test-api-key' + apiKey: 'test-api-key', }; client = new UpsunClient(config); }); @@ -20,9 +20,9 @@ describe('UpsunClient', () => { it('should initialize with default config', () => { const defaultClient = new UpsunClient(); expect(defaultClient).toBeDefined(); - expect(defaultClient.activity).toBeDefined(); - expect(defaultClient.project).toBeDefined(); - expect(defaultClient.environment).toBeDefined(); + expect(defaultClient.activities).toBeDefined(); + expect(defaultClient.projects).toBeDefined(); + expect(defaultClient.environments).toBeDefined(); }); it('should initialize with custom config', () => { @@ -32,9 +32,9 @@ describe('UpsunClient', () => { apiKey: 'custom-key', token_endpoint: 'custom/token', refresh_endpoint: 'custom/refresh', - clientId: 'custom-client' + clientId: 'custom-client', }; - + const customClient = new UpsunClient(customConfig); expect(customClient).toBeDefined(); }); @@ -42,25 +42,25 @@ describe('UpsunClient', () => { describe('task initialization', () => { it('should initialize all task instances', () => { - expect(client.activity).toBeDefined(); - expect(client.application).toBeDefined(); - expect(client.backup).toBeDefined(); - expect(client.certificate).toBeDefined(); - expect(client.domain).toBeDefined(); - expect(client.environment).toBeDefined(); + expect(client.activities).toBeDefined(); + expect(client.applications).toBeDefined(); + expect(client.backups).toBeDefined(); + expect(client.certificates).toBeDefined(); + expect(client.domains).toBeDefined(); + expect(client.environments).toBeDefined(); expect(client.metrics).toBeDefined(); - expect(client.mount).toBeDefined(); - expect(client.operation).toBeDefined(); - expect(client.organization).toBeDefined(); - expect(client.project).toBeDefined(); - expect(client.route).toBeDefined(); - expect(client.service).toBeDefined(); - expect(client.sourceOperation).toBeDefined(); - expect(client.team).toBeDefined(); - expect(client.user).toBeDefined(); - expect(client.variable).toBeDefined(); - expect(client.worker).toBeDefined(); - expect(client.resource).toBeDefined(); + expect(client.mounts).toBeDefined(); + expect(client.operations).toBeDefined(); + expect(client.organizations).toBeDefined(); + expect(client.projects).toBeDefined(); + expect(client.routes).toBeDefined(); + expect(client.services).toBeDefined(); + expect(client.sourceOperations).toBeDefined(); + expect(client.teams).toBeDefined(); + expect(client.users).toBeDefined(); + expect(client.variables).toBeDefined(); + expect(client.workers).toBeDefined(); + expect(client.resources).toBeDefined(); }); }); diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 0000000..dc379f5 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "./dist-tests", + "noEmit": true, + "isolatedModules": true + }, + "include": ["src/**/*", "tests/**/*"], + "exclude": ["node_modules", "dist", "dist-tests"] +}