├── .eslintignore ├── .eslintrc ├── .github └── workflows │ ├── gh-pages.yml │ ├── publish.yml │ └── tests.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── examples ├── .eslintrc ├── README.md ├── getCurrentMemberInfo.ts ├── listCustomFields.ts ├── logo.png └── uploadFileToStory.ts ├── package.json ├── schema └── shortcut.swagger.json ├── scripts └── add-typedoc-comments.ts ├── src ├── ShortcutClient.ts ├── __tests__ │ ├── ShortcutApi-unmock-test.ts │ └── index-test.ts ├── generated │ ├── Api.ts │ ├── data-contracts.ts │ └── http-client.ts ├── index.ts └── types.d.ts ├── templates └── http-client.ejs ├── tsconfig.json ├── tsup.config.ts ├── typedoc.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | /src/generated 2 | /lib 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "extends": [ 4 | "airbnb-base", 5 | "plugin:@typescript-eslint/recommended", 6 | "prettier", 7 | "plugin:prettier/recommended" 8 | ], 9 | "parserOptions": { 10 | "sourceType": "module" 11 | }, 12 | "settings": { 13 | "import/extensions": [ 14 | ".js", 15 | ".ts" 16 | ], 17 | "import/parsers": { 18 | "@typescript-eslint/parser": [ 19 | ".ts" 20 | ] 21 | }, 22 | "import/resolver": { 23 | "node": { 24 | "extensions": [ 25 | ".js", 26 | ".ts" 27 | ] 28 | } 29 | } 30 | }, 31 | "plugins": [ 32 | "import", 33 | "jest", 34 | "prettier" 35 | ], 36 | "env": { 37 | "jest": true, 38 | "es6": true 39 | }, 40 | "rules": { 41 | "no-undef": 0, 42 | "import/extensions": 0, 43 | "import/prefer-default-export": 0, 44 | "@typescript-eslint/camelcase": 0, 45 | "@typescript-eslint/no-explicit-any": 0, 46 | "no-restricted-exports": 0 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: "GitHub Pages" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write # Required for deploying pages 13 | pages: write # Required for deploying pages 14 | steps: 15 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 16 | 17 | - name: Setup Node 18 | uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 19 | with: 20 | node-version: 'lts/*' 21 | cache: 'yarn' 22 | 23 | - run: yarn install 24 | - run: yarn build:client 25 | - run: yarn build:docs 26 | 27 | - name: Deploy 28 | uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 29 | with: 30 | github_token: ${{ secrets.GITHUB_TOKEN }} 31 | publish_dir: ./docs 32 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Package to npmjs 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | contents: read 12 | id-token: write 13 | steps: 14 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 15 | - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 16 | with: 17 | node-version: '22.x' 18 | cache: 'yarn' 19 | registry-url: 'https://registry.npmjs.org' 20 | - name: Install dependencies 21 | run: yarn --frozen-lockfile 22 | - run: npm publish --provenance --access public 23 | env: 24 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 25 | - name: Rename package to @useshortcut/client 26 | run: | 27 | sed -i 's/"name": ".*"/"name": "@useshortcut\/client"/' package.json 28 | - name: Publish under @useshortcut scope 29 | run: npm publish --provenance --access public 30 | env: 31 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 32 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 14 | - name: Use Node.js 15 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 16 | with: 17 | node-version: '22.x' 18 | cache: 'yarn' 19 | - name: Install dependencies 20 | run: yarn install --frozen-lockfile 21 | - name: Run linter 22 | run: yarn lint 23 | 24 | validate-schema: 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 28 | - name: Use Node.js 29 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 30 | with: 31 | node-version: '22.x' 32 | cache: 'yarn' 33 | - name: Install dependencies 34 | run: yarn install --frozen-lockfile 35 | - name: Validate schema 36 | run: yarn validate:schema 37 | 38 | test: 39 | runs-on: ubuntu-latest 40 | steps: 41 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 42 | - name: Use Node.js 43 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 44 | with: 45 | node-version: '22.x' 46 | cache: 'yarn' 47 | - name: Install dependencies 48 | run: yarn install --frozen-lockfile 49 | - name: Run Jest 50 | run: yarn test 51 | 52 | format-check: 53 | runs-on: ubuntu-latest 54 | steps: 55 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 56 | - name: Use Node.js 57 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 58 | with: 59 | node-version: '22.x' 60 | cache: 'yarn' 61 | - name: Install dependencies 62 | run: yarn install --frozen-lockfile 63 | - name: Check formatting 64 | run: yarn format:check 65 | 66 | validate-examples: 67 | runs-on: ubuntu-latest 68 | steps: 69 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 70 | - name: Use Node.js 71 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 72 | with: 73 | node-version: '22.x' 74 | cache: 'yarn' 75 | - name: Install dependencies 76 | run: yarn install --frozen-lockfile 77 | - name: Validate examples (run tsc) 78 | run: yarn validate:examples 79 | 80 | build: 81 | runs-on: ubuntu-latest 82 | steps: 83 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 84 | - name: Use Node.js 85 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 86 | with: 87 | node-version: '22.x' 88 | cache: 'yarn' 89 | - name: Install dependencies 90 | run: yarn install --frozen-lockfile 91 | - name: Build 92 | run: yarn build 93 | 94 | check-exports: 95 | runs-on: ubuntu-latest 96 | steps: 97 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 98 | - name: Use Node.js 99 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 100 | with: 101 | node-version: '22.x' 102 | cache: 'yarn' 103 | - name: Install dependencies 104 | run: yarn install --frozen-lockfile 105 | - name: Check exports 106 | run: yarn check-exports 107 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | lib/ 4 | node_modules/ 5 | npm-debug.log 6 | package-lock.json 7 | /docs 8 | *.log 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .DS_Store 3 | /src 4 | **/__tests__/** 5 | /docs 6 | /schema 7 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | /src/generated 2 | /schema 3 | /lib 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": true, 4 | "trailingComma": "all", 5 | "arrowParens": "always", 6 | "overrides": [ 7 | { 8 | "files": "*.ts", 9 | "options": { 10 | "parser": "typescript" 11 | } 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Shortcut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @shortcut/client 2 | 3 | Shortcut's logo 4 | 5 | [![Version](https://badge.fury.io/js/@shortcut%2Fclient.svg)](https://badge.fury.io/js/@shortcut%2Fclient) 6 | [![Monthly Downloads](https://img.shields.io/npm/dm/@shortcut%2Fclient)](https://www.npmjs.org/package/@shortcut%2Fclient) 7 | [![GitHub License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/useshortcut/shortcut-client-js/blob/main/LICENSE) 8 | [![PRs welcome!](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)]() 9 | [![X](https://img.shields.io/twitter/follow/shortcut.svg?label=Follow%20@shortcut)](https://twitter.com/intent/follow?screen_name=shortcut) 10 | 11 | A library for interacting with the Shortcut REST API. 12 | 13 |
14 | 15 | ## Getting Started 16 | 17 | ### Installation 18 | 19 | ```shell 20 | npm install @shortcut/client 21 | ``` 22 | 23 | > [!IMPORTANT] 24 | > Our legacy npm organization namespace is `@useshortcut`. 25 | > 26 | > While it will still contain copies of all future released package versions, we **strongly** recommend switching to our primary `@shortcut` organization namespace. 27 | 28 | ### How to Get an API Token 29 | 30 | The Shortcut API uses token-based authentication, you will need one to use this library. 31 | 32 | To generate an API token, go to https://app.shortcut.com/settings/account/api-tokens. 33 | 34 | To make it easier to explore our API, we recommend saving this token as an environment variable in your local dev environment: 35 | 36 | ```bash 37 | export SHORTCUT_API_TOKEN="YOUR API TOKEN HERE" 38 | ``` 39 | 40 | This will allow you to copy and paste many examples in the documentation to try them out. 41 | 42 | > [!NOTE] 43 | > Requests made with a missing or invalid token will get a `401 Unauthorized` response. 44 | 45 | > [!NOTE] 46 | > All requests must be made over HTTPS. 47 | 48 | > [!CAUTION] 49 | > Tokens provide complete access to your Shortcut account, **so keep them secure**. 50 | > 51 | > Don’t paste them into your source code, use an environment variable instead. 52 | > 53 | > For security reasons, we will immediately invalidate any tokens we find have been made public. 54 | 55 | ## Usage 56 | 57 | To see all available exports, take a look at the [API documentation](https://useshortcut.github.io/shortcut-client-js/) or check out the `.d.ts` files in this repository. 58 | 59 | ```javascript 60 | import { ShortcutClient } from '@shortcut/client'; 61 | // const { ShortcutClient } = require('@shortcut/client'); 62 | 63 | const shortcut = new ShortcutClient('YOUR_API_TOKEN'); // See https://github.com/useshortcut/shortcut-client-js#how-to-get-an-api-token 64 | 65 | shortcut.getCurrentMemberInfo().then((response) => console.log(response?.data)); 66 | 67 | shortcut.listProjects().then((response) => console.log(response?.data)); 68 | ``` 69 | 70 | ## Play with It 71 | 72 | You can play with it in your web browser with this live playground: 73 | 74 | - [CodeSandbox](https://codesandbox.io/s/useshortcut-client-playground-48kq1) 75 | 76 | ## Documentation 77 | 78 | [Documentation for this client](https://useshortcut.github.io/shortcut-client-js/). 79 | 80 | [Documentation for the REST API](https://developer.shortcut.com/api/rest/v3). 81 | -------------------------------------------------------------------------------- /examples/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-console": 0, 4 | "import/no-extraneous-dependencies": 0 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | This folder contains ready-to-use examples. 4 | 5 | ## Usage 6 | 7 | You will need to set an environment variable with your API Token. See [How to Get an API Token](../README.md#how-to-get-an-api-token). 8 | 9 | Then, you can run the file you want with: 10 | 11 | ```bash 12 | SHORTCUT_API_TOKEN=YOUR_API_TOKEN npx ts-node FILE_EXAMPLE 13 | ``` -------------------------------------------------------------------------------- /examples/getCurrentMemberInfo.ts: -------------------------------------------------------------------------------- 1 | import { ShortcutClient } from '../src'; 2 | 3 | const shortcut = new ShortcutClient(process.env.SHORTCUT_API_TOKEN); // See https://github.com/useshortcut/shortcut-client-js#how-to-get-an-api-token 4 | 5 | shortcut.getCurrentMemberInfo().then((response) => console.log(response?.data)); 6 | -------------------------------------------------------------------------------- /examples/listCustomFields.ts: -------------------------------------------------------------------------------- 1 | import { ShortcutClient } from '../src'; 2 | 3 | const shortcut = new ShortcutClient(process.env.SHORTCUT_API_TOKEN); // See https://github.com/useshortcut/shortcut-client-js#how-to-get-an-api-token 4 | 5 | shortcut.listCustomFields().then((response) => console.log(response?.data)); 6 | -------------------------------------------------------------------------------- /examples/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useshortcut/shortcut-client-js/732948ceb1c60ba15006f6621673c73e1c3bd5d4/examples/logo.png -------------------------------------------------------------------------------- /examples/uploadFileToStory.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as streamToBlob from 'stream-to-blob'; 3 | 4 | import { ShortcutClient } from '../src'; 5 | 6 | (async () => { 7 | const shortcut = new ShortcutClient(process.env.SHORTCUT_API_TOKEN); // See https://github.com/useshortcut/shortcut-client-js#how-to-get-an-api-token 8 | 9 | const FILE_PATH = `${__dirname}/logo.png`; 10 | 11 | const { data: workflows } = await shortcut.listWorkflows(); 12 | 13 | const { data: story } = await shortcut.createStory({ 14 | name: 'Upload a file to a story', 15 | workflow_state_id: workflows[0].states[0].id, 16 | }); 17 | 18 | console.log('Story created with ID:', story.id); 19 | 20 | // This is proper to Node, replace this based on your environment 21 | const fileStream = fs.createReadStream(FILE_PATH); 22 | 23 | const { data: file } = await shortcut.uploadFiles({ 24 | story_id: story.id, 25 | file0: (await streamToBlob(fileStream)) as any, // On Web, this is expecting a File object, but on Node, it's a ReadableStream 26 | }); 27 | 28 | console.log(file); 29 | })(); 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@shortcut/client", 3 | "version": "2.0.0", 4 | "description": "A Promise based library to the Shortcut REST API", 5 | "homepage": "https://github.com/useshortcut/shortcut-client-js", 6 | "bugs": { 7 | "url": "https://github.com/useshortcut/shortcut-client-js/issues" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/useshortcut/shortcut-client-js.git" 12 | }, 13 | "license": "MIT", 14 | "sideEffects": false, 15 | "type": "commonjs", 16 | "exports": { 17 | ".": { 18 | "import": { 19 | "types": "./lib/index.d.mts", 20 | "default": "./lib/index.mjs" 21 | }, 22 | "require": { 23 | "types": "./lib/index.d.ts", 24 | "default": "./lib/index.js" 25 | } 26 | } 27 | }, 28 | "main": "./lib/index.js", 29 | "module": "./lib/index.mjs", 30 | "types": "./lib/index.d.ts", 31 | "files": [ 32 | "lib" 33 | ], 34 | "scripts": { 35 | "build": "yarn build:client && yarn build:add-typedoc-comments && tsup", 36 | "build:add-typedoc-comments": "npx jscodeshift -t scripts/add-typedoc-comments.ts --extensions=ts --parser=ts src/generated/**", 37 | "build:client": "swagger-typescript-api generate --path ./schema/shortcut.swagger.json --output ./src/generated --clean-output --axios --modular --templates ./templates", 38 | "build:docs": "typedoc ./src --exclude 'src/__tests__/**'", 39 | "check-exports": "attw --pack .", 40 | "format": "prettier --write -l *.{json,md,prettierrc} '{src,scripts}/**/*.ts'", 41 | "format:check": "prettier --check *.{json,md,prettierrc} '{src,scripts}/**/*.ts'", 42 | "lint": "eslint 'src/**/*.{js,ts}'", 43 | "prepublishOnly": "yarn build", 44 | "sync:schema": "curl --silent https://developer.shortcut.com/api/rest/v3/shortcut.swagger.json --output ./schema/shortcut.swagger.json && yarn validate:schema", 45 | "test": "jest", 46 | "validate:examples": "npx tsc examples/*.ts --noEmit", 47 | "validate:schema": "swagger-cli validate ./schema/shortcut.swagger.json" 48 | }, 49 | "jest": { 50 | "preset": "ts-jest", 51 | "testEnvironment": "node", 52 | "testPathIgnorePatterns": [ 53 | "/lib/", 54 | "/node_modules/" 55 | ] 56 | }, 57 | "dependencies": { 58 | "axios": "^1.9.0" 59 | }, 60 | "devDependencies": { 61 | "@arethetypeswrong/cli": "^0.18.1", 62 | "@total-typescript/tsconfig": "^1.0.4", 63 | "@types/glob": "^8.1.0", 64 | "@types/jest": "^29.5.14", 65 | "@types/jscodeshift": "17.3.0", 66 | "@types/node": "^22.15.30", 67 | "@typescript-eslint/eslint-plugin": "^8.33.1", 68 | "@typescript-eslint/parser": "^8.33.1", 69 | "eslint": "^8.57.1", 70 | "eslint-config-airbnb-base": "^15.0.0", 71 | "eslint-config-prettier": "^10.1.5", 72 | "eslint-plugin-import": "^2.31.0", 73 | "eslint-plugin-jest": "^28.12.0", 74 | "eslint-plugin-prettier": "^5.4.1", 75 | "glob": "^11.0.2", 76 | "jest": "^29.7.0", 77 | "jscodeshift": "^17.3.0", 78 | "prettier": "^3.5.3", 79 | "stream-to-blob": "^2.0.1", 80 | "swagger-cli": "^4.0.4", 81 | "swagger-typescript-api": "^13.2.0", 82 | "ts-jest": "^29.3.4", 83 | "tsup": "^8.5.0", 84 | "typedoc": "0.28.5", 85 | "typedoc-plugin-merge-modules": "7.0.0", 86 | "typescript": "^5.8.3" 87 | }, 88 | "readme": "https://github.com/useshortcut/shortcut-client-js#readme" 89 | } 90 | -------------------------------------------------------------------------------- /scripts/add-typedoc-comments.ts: -------------------------------------------------------------------------------- 1 | import { API, FileInfo } from 'jscodeshift'; 2 | 3 | export default function transformer(file: FileInfo, api: API) { 4 | const j = api.jscodeshift; 5 | const root = j(file.source); 6 | 7 | return root 8 | .find(j.ClassDeclaration) 9 | .filter( 10 | (path) => 11 | path.value.id?.type === 'Identifier' && 12 | ['Api', 'HttpClient'].includes(path.value.id.name), 13 | ) 14 | .forEach((path) => { 15 | const target = 16 | path.parent.value.type === 'ExportNamedDeclaration' 17 | ? path.parent 18 | : path; 19 | 20 | const desc = 21 | path.value.id?.name === 'Api' 22 | ? "\n * Please don't use this class directly, instead use the `ShortcutClient` class we provided which is extending this class to add headers for authorization." 23 | : '\n'; 24 | 25 | target.insertBefore(`/** ${desc} * @internal\n * @private\n */`); 26 | }) 27 | .toSource(); 28 | } 29 | -------------------------------------------------------------------------------- /src/ShortcutClient.ts: -------------------------------------------------------------------------------- 1 | import { Api } from './generated/Api'; 2 | import type { ApiConfig } from './generated/http-client'; 3 | 4 | export class ShortcutClient< 5 | SecurityDataType = unknown, 6 | > extends Api { 7 | constructor(apiToken: string, config: ApiConfig = {}) { 8 | if (apiToken == null || typeof apiToken !== 'string') { 9 | // eslint-disable-next-line no-console 10 | console.error('You need to supply an API Token.'); 11 | } 12 | 13 | super({ 14 | headers: { 'Shortcut-Token': apiToken, ...config.headers }, 15 | ...config, 16 | }); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/__tests__/ShortcutApi-unmock-test.ts: -------------------------------------------------------------------------------- 1 | import { ShortcutClient } from '../ShortcutClient'; 2 | 3 | jest.unmock('axios'); 4 | 5 | describe('ShortcutClient', () => { 6 | const token = 'SOME-TOKEN'; 7 | 8 | it('uses the expected baseURL', () => { 9 | const shortcut = new ShortcutClient(token); 10 | 11 | expect(shortcut.instance.defaults.baseURL).toBe( 12 | 'https://api.app.shortcut.com', 13 | ); 14 | }); 15 | 16 | it('adds Shortcut-Token to default headers', async () => { 17 | const shortcut = new ShortcutClient(token); 18 | 19 | expect(shortcut.instance.defaults.headers).toHaveProperty( 20 | 'Shortcut-Token', 21 | token, 22 | ); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /src/__tests__/index-test.ts: -------------------------------------------------------------------------------- 1 | import { ShortcutClient } from '../index'; 2 | 3 | describe('index', () => { 4 | it('exposes ShortcutClient', () => { 5 | expect(ShortcutClient).toBeDefined(); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /src/generated/Api.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-nocheck 4 | /* 5 | * --------------------------------------------------------------- 6 | * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## 7 | * ## ## 8 | * ## AUTHOR: acacode ## 9 | * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## 10 | * --------------------------------------------------------------- 11 | */ 12 | 13 | import { 14 | Category, 15 | CreateCategory, 16 | CreateCommentComment, 17 | CreateEntityTemplate, 18 | CreateEpic, 19 | CreateEpicComment, 20 | CreateEpicHealth, 21 | CreateGenericIntegration, 22 | CreateGroup, 23 | CreateIteration, 24 | CreateLabelParams, 25 | CreateLinkedFile, 26 | CreateMilestone, 27 | CreateObjective, 28 | CreateOrDeleteStoryReaction, 29 | CreateProject, 30 | CreateStories, 31 | CreateStoryComment, 32 | CreateStoryFromTemplateParams, 33 | CreateStoryLink, 34 | CreateStoryParams, 35 | CreateTask, 36 | CustomField, 37 | DataConflictError, 38 | DeleteStories, 39 | EntityTemplate, 40 | Epic, 41 | EpicPaginatedResults, 42 | EpicSearchResults, 43 | EpicSlim, 44 | EpicWorkflow, 45 | Group, 46 | Health, 47 | History, 48 | Iteration, 49 | IterationSearchResults, 50 | IterationSlim, 51 | KeyResult, 52 | Label, 53 | LinkedFile, 54 | MaxSearchResultsExceededError, 55 | Member, 56 | MemberInfo, 57 | Milestone, 58 | Objective, 59 | ObjectiveSearchResults, 60 | Project, 61 | Repository, 62 | SearchResults, 63 | SearchStories, 64 | Story, 65 | StoryComment, 66 | StoryLink, 67 | StoryReaction, 68 | StorySearchResults, 69 | StorySlim, 70 | Task, 71 | ThreadedComment, 72 | UnusableEntitlementError, 73 | UpdateCategory, 74 | UpdateComment, 75 | UpdateCustomField, 76 | UpdateEntityTemplate, 77 | UpdateEpic, 78 | UpdateFile, 79 | UpdateGroup, 80 | UpdateHealth, 81 | UpdateIteration, 82 | UpdateKeyResult, 83 | UpdateLabel, 84 | UpdateLinkedFile, 85 | UpdateMilestone, 86 | UpdateObjective, 87 | UpdateProject, 88 | UpdateStories, 89 | UpdateStory, 90 | UpdateStoryComment, 91 | UpdateStoryLink, 92 | UpdateTask, 93 | UploadedFile, 94 | Workflow, 95 | } from "./data-contracts"; 96 | import { ContentType, HttpClient, RequestParams } from "./http-client"; 97 | 98 | /** 99 | * Please don't use this class directly, instead use the `ShortcutClient` class we provided which is extending this class to add headers for authorization. * @internal 100 | * @private 101 | */ 102 | 103 | export class Api< 104 | SecurityDataType = unknown, 105 | > extends HttpClient { 106 | /** 107 | * @description List Categories returns a list of all Categories and their attributes. 108 | * 109 | * @name ListCategories 110 | * @summary List Categories 111 | * @request GET:/api/v3/categories 112 | * @secure 113 | */ 114 | listCategories = (params: RequestParams = {}) => 115 | this.request({ 116 | path: `/api/v3/categories`, 117 | method: "GET", 118 | secure: true, 119 | format: "json", 120 | ...params, 121 | }); 122 | /** 123 | * @description Create Category allows you to create a new Category in Shortcut. 124 | * 125 | * @name CreateCategory 126 | * @summary Create Category 127 | * @request POST:/api/v3/categories 128 | * @secure 129 | */ 130 | createCategory = ( 131 | CreateCategory: CreateCategory, 132 | params: RequestParams = {}, 133 | ) => 134 | this.request({ 135 | path: `/api/v3/categories`, 136 | method: "POST", 137 | body: CreateCategory, 138 | secure: true, 139 | type: ContentType.Json, 140 | format: "json", 141 | ...params, 142 | }); 143 | /** 144 | * @description Get Category returns information about the selected Category. 145 | * 146 | * @name GetCategory 147 | * @summary Get Category 148 | * @request GET:/api/v3/categories/{category-public-id} 149 | * @secure 150 | */ 151 | getCategory = (categoryPublicId: number, params: RequestParams = {}) => 152 | this.request({ 153 | path: `/api/v3/categories/${categoryPublicId}`, 154 | method: "GET", 155 | secure: true, 156 | format: "json", 157 | ...params, 158 | }); 159 | /** 160 | * @description Update Category allows you to replace a Category name with another name. If you try to name a Category something that already exists, you will receive a 422 response. 161 | * 162 | * @name UpdateCategory 163 | * @summary Update Category 164 | * @request PUT:/api/v3/categories/{category-public-id} 165 | * @secure 166 | */ 167 | updateCategory = ( 168 | categoryPublicId: number, 169 | UpdateCategory: UpdateCategory, 170 | params: RequestParams = {}, 171 | ) => 172 | this.request({ 173 | path: `/api/v3/categories/${categoryPublicId}`, 174 | method: "PUT", 175 | body: UpdateCategory, 176 | secure: true, 177 | type: ContentType.Json, 178 | format: "json", 179 | ...params, 180 | }); 181 | /** 182 | * @description Delete Category can be used to delete any Category. 183 | * 184 | * @name DeleteCategory 185 | * @summary Delete Category 186 | * @request DELETE:/api/v3/categories/{category-public-id} 187 | * @secure 188 | */ 189 | deleteCategory = (categoryPublicId: number, params: RequestParams = {}) => 190 | this.request({ 191 | path: `/api/v3/categories/${categoryPublicId}`, 192 | method: "DELETE", 193 | secure: true, 194 | ...params, 195 | }); 196 | /** 197 | * @description List Category Milestones returns a list of all Milestones with the Category. 198 | * 199 | * @name ListCategoryMilestones 200 | * @summary List Category Milestones 201 | * @request GET:/api/v3/categories/{category-public-id}/milestones 202 | * @secure 203 | */ 204 | listCategoryMilestones = ( 205 | categoryPublicId: number, 206 | params: RequestParams = {}, 207 | ) => 208 | this.request({ 209 | path: `/api/v3/categories/${categoryPublicId}/milestones`, 210 | method: "GET", 211 | secure: true, 212 | format: "json", 213 | ...params, 214 | }); 215 | /** 216 | * @description Returns a list of all Objectives with the Category. 217 | * 218 | * @name ListCategoryObjectives 219 | * @summary List Category Objectives 220 | * @request GET:/api/v3/categories/{category-public-id}/objectives 221 | * @secure 222 | */ 223 | listCategoryObjectives = ( 224 | categoryPublicId: number, 225 | params: RequestParams = {}, 226 | ) => 227 | this.request({ 228 | path: `/api/v3/categories/${categoryPublicId}/objectives`, 229 | method: "GET", 230 | secure: true, 231 | format: "json", 232 | ...params, 233 | }); 234 | /** 235 | * No description 236 | * 237 | * @name ListCustomFields 238 | * @summary List Custom Fields 239 | * @request GET:/api/v3/custom-fields 240 | * @secure 241 | */ 242 | listCustomFields = (params: RequestParams = {}) => 243 | this.request({ 244 | path: `/api/v3/custom-fields`, 245 | method: "GET", 246 | secure: true, 247 | format: "json", 248 | ...params, 249 | }); 250 | /** 251 | * No description 252 | * 253 | * @name GetCustomField 254 | * @summary Get Custom Field 255 | * @request GET:/api/v3/custom-fields/{custom-field-public-id} 256 | * @secure 257 | */ 258 | getCustomField = (customFieldPublicId: string, params: RequestParams = {}) => 259 | this.request({ 260 | path: `/api/v3/custom-fields/${customFieldPublicId}`, 261 | method: "GET", 262 | secure: true, 263 | format: "json", 264 | ...params, 265 | }); 266 | /** 267 | * @description Update Custom Field can be used to update the definition of a Custom Field. The order of items in the 'values' collection is interpreted to be their ascending sort order.To delete an existing enum value, simply omit it from the 'values' collection. New enum values may be created inline by including an object in the 'values' collection having a 'value' entry with no 'id' (eg. {'value': 'myNewValue', 'color_key': 'green'}). 268 | * 269 | * @name UpdateCustomField 270 | * @summary Update Custom Field 271 | * @request PUT:/api/v3/custom-fields/{custom-field-public-id} 272 | * @secure 273 | */ 274 | updateCustomField = ( 275 | customFieldPublicId: string, 276 | UpdateCustomField: UpdateCustomField, 277 | params: RequestParams = {}, 278 | ) => 279 | this.request({ 280 | path: `/api/v3/custom-fields/${customFieldPublicId}`, 281 | method: "PUT", 282 | body: UpdateCustomField, 283 | secure: true, 284 | type: ContentType.Json, 285 | format: "json", 286 | ...params, 287 | }); 288 | /** 289 | * No description 290 | * 291 | * @name DeleteCustomField 292 | * @summary Delete Custom Field 293 | * @request DELETE:/api/v3/custom-fields/{custom-field-public-id} 294 | * @secure 295 | */ 296 | deleteCustomField = ( 297 | customFieldPublicId: string, 298 | params: RequestParams = {}, 299 | ) => 300 | this.request({ 301 | path: `/api/v3/custom-fields/${customFieldPublicId}`, 302 | method: "DELETE", 303 | secure: true, 304 | ...params, 305 | }); 306 | /** 307 | * @description List all the entity templates for the Workspace. 308 | * 309 | * @name ListEntityTemplates 310 | * @summary List Entity Templates 311 | * @request GET:/api/v3/entity-templates 312 | * @secure 313 | */ 314 | listEntityTemplates = (params: RequestParams = {}) => 315 | this.request({ 316 | path: `/api/v3/entity-templates`, 317 | method: "GET", 318 | secure: true, 319 | format: "json", 320 | ...params, 321 | }); 322 | /** 323 | * @description Create a new entity template for the Workspace. 324 | * 325 | * @name CreateEntityTemplate 326 | * @summary Create Entity Template 327 | * @request POST:/api/v3/entity-templates 328 | * @secure 329 | */ 330 | createEntityTemplate = ( 331 | CreateEntityTemplate: CreateEntityTemplate, 332 | params: RequestParams = {}, 333 | ) => 334 | this.request({ 335 | path: `/api/v3/entity-templates`, 336 | method: "POST", 337 | body: CreateEntityTemplate, 338 | secure: true, 339 | type: ContentType.Json, 340 | format: "json", 341 | ...params, 342 | }); 343 | /** 344 | * @description Disables the Story Template feature for the Workspace. 345 | * 346 | * @name DisableStoryTemplates 347 | * @summary Disable Story Templates 348 | * @request PUT:/api/v3/entity-templates/disable 349 | * @secure 350 | */ 351 | disableStoryTemplates = (params: RequestParams = {}) => 352 | this.request({ 353 | path: `/api/v3/entity-templates/disable`, 354 | method: "PUT", 355 | secure: true, 356 | ...params, 357 | }); 358 | /** 359 | * @description Enables the Story Template feature for the Workspace. 360 | * 361 | * @name EnableStoryTemplates 362 | * @summary Enable Story Templates 363 | * @request PUT:/api/v3/entity-templates/enable 364 | * @secure 365 | */ 366 | enableStoryTemplates = (params: RequestParams = {}) => 367 | this.request({ 368 | path: `/api/v3/entity-templates/enable`, 369 | method: "PUT", 370 | secure: true, 371 | ...params, 372 | }); 373 | /** 374 | * @description Get Entity Template returns information about a given entity template. 375 | * 376 | * @name GetEntityTemplate 377 | * @summary Get Entity Template 378 | * @request GET:/api/v3/entity-templates/{entity-template-public-id} 379 | * @secure 380 | */ 381 | getEntityTemplate = ( 382 | entityTemplatePublicId: string, 383 | params: RequestParams = {}, 384 | ) => 385 | this.request({ 386 | path: `/api/v3/entity-templates/${entityTemplatePublicId}`, 387 | method: "GET", 388 | secure: true, 389 | format: "json", 390 | ...params, 391 | }); 392 | /** 393 | * @description Update an entity template's name or its contents. 394 | * 395 | * @name UpdateEntityTemplate 396 | * @summary Update Entity Template 397 | * @request PUT:/api/v3/entity-templates/{entity-template-public-id} 398 | * @secure 399 | */ 400 | updateEntityTemplate = ( 401 | entityTemplatePublicId: string, 402 | UpdateEntityTemplate: UpdateEntityTemplate, 403 | params: RequestParams = {}, 404 | ) => 405 | this.request({ 406 | path: `/api/v3/entity-templates/${entityTemplatePublicId}`, 407 | method: "PUT", 408 | body: UpdateEntityTemplate, 409 | secure: true, 410 | type: ContentType.Json, 411 | format: "json", 412 | ...params, 413 | }); 414 | /** 415 | * No description 416 | * 417 | * @name DeleteEntityTemplate 418 | * @summary Delete Entity Template 419 | * @request DELETE:/api/v3/entity-templates/{entity-template-public-id} 420 | * @secure 421 | */ 422 | deleteEntityTemplate = ( 423 | entityTemplatePublicId: string, 424 | params: RequestParams = {}, 425 | ) => 426 | this.request({ 427 | path: `/api/v3/entity-templates/${entityTemplatePublicId}`, 428 | method: "DELETE", 429 | secure: true, 430 | ...params, 431 | }); 432 | /** 433 | * @description Returns the Epic Workflow for the Workspace. 434 | * 435 | * @name GetEpicWorkflow 436 | * @summary Get Epic Workflow 437 | * @request GET:/api/v3/epic-workflow 438 | * @secure 439 | */ 440 | getEpicWorkflow = (params: RequestParams = {}) => 441 | this.request({ 442 | path: `/api/v3/epic-workflow`, 443 | method: "GET", 444 | secure: true, 445 | format: "json", 446 | ...params, 447 | }); 448 | /** 449 | * @description List Epics returns a list of all Epics and their attributes. 450 | * 451 | * @name ListEpics 452 | * @summary List Epics 453 | * @request GET:/api/v3/epics 454 | * @secure 455 | */ 456 | listEpics = ( 457 | query?: { 458 | /** A true/false boolean indicating whether to return Epics with their descriptions. */ 459 | includes_description?: boolean; 460 | }, 461 | params: RequestParams = {}, 462 | ) => 463 | this.request({ 464 | path: `/api/v3/epics`, 465 | method: "GET", 466 | query: query, 467 | secure: true, 468 | format: "json", 469 | ...params, 470 | }); 471 | /** 472 | * @description Create Epic allows you to create a new Epic in Shortcut. 473 | * 474 | * @name CreateEpic 475 | * @summary Create Epic 476 | * @request POST:/api/v3/epics 477 | * @secure 478 | */ 479 | createEpic = (CreateEpic: CreateEpic, params: RequestParams = {}) => 480 | this.request({ 481 | path: `/api/v3/epics`, 482 | method: "POST", 483 | body: CreateEpic, 484 | secure: true, 485 | type: ContentType.Json, 486 | format: "json", 487 | ...params, 488 | }); 489 | /** 490 | * @description List Epics with pagination returns a paginated list of Epics and their attributes. 491 | * 492 | * @name ListEpicsPaginated 493 | * @summary List Epics Paginated 494 | * @request GET:/api/v3/epics/paginated 495 | * @secure 496 | */ 497 | listEpicsPaginated = ( 498 | query?: { 499 | /** A true/false boolean indicating whether to return Epics with their descriptions. */ 500 | includes_description?: boolean; 501 | /** 502 | * The page number to return, starting with 1. Defaults to 1. 503 | * @format int64 504 | */ 505 | page?: number; 506 | /** 507 | * The number of Epics to return per page. Minimum 1, maximum 250, default 10. 508 | * @format int64 509 | */ 510 | page_size?: number; 511 | }, 512 | params: RequestParams = {}, 513 | ) => 514 | this.request({ 515 | path: `/api/v3/epics/paginated`, 516 | method: "GET", 517 | query: query, 518 | secure: true, 519 | format: "json", 520 | ...params, 521 | }); 522 | /** 523 | * @description Get Epic returns information about the selected Epic. 524 | * 525 | * @name GetEpic 526 | * @summary Get Epic 527 | * @request GET:/api/v3/epics/{epic-public-id} 528 | * @secure 529 | */ 530 | getEpic = (epicPublicId: number, params: RequestParams = {}) => 531 | this.request({ 532 | path: `/api/v3/epics/${epicPublicId}`, 533 | method: "GET", 534 | secure: true, 535 | format: "json", 536 | ...params, 537 | }); 538 | /** 539 | * @description Update Epic can be used to update numerous fields in the Epic. The only required parameter is Epic ID, which can be found in the Shortcut UI. 540 | * 541 | * @name UpdateEpic 542 | * @summary Update Epic 543 | * @request PUT:/api/v3/epics/{epic-public-id} 544 | * @secure 545 | */ 546 | updateEpic = ( 547 | epicPublicId: number, 548 | UpdateEpic: UpdateEpic, 549 | params: RequestParams = {}, 550 | ) => 551 | this.request({ 552 | path: `/api/v3/epics/${epicPublicId}`, 553 | method: "PUT", 554 | body: UpdateEpic, 555 | secure: true, 556 | type: ContentType.Json, 557 | format: "json", 558 | ...params, 559 | }); 560 | /** 561 | * @description Delete Epic can be used to delete the Epic. The only required parameter is Epic ID. 562 | * 563 | * @name DeleteEpic 564 | * @summary Delete Epic 565 | * @request DELETE:/api/v3/epics/{epic-public-id} 566 | * @secure 567 | */ 568 | deleteEpic = (epicPublicId: number, params: RequestParams = {}) => 569 | this.request({ 570 | path: `/api/v3/epics/${epicPublicId}`, 571 | method: "DELETE", 572 | secure: true, 573 | ...params, 574 | }); 575 | /** 576 | * @description Get a list of all Comments on an Epic. 577 | * 578 | * @name ListEpicComments 579 | * @summary List Epic Comments 580 | * @request GET:/api/v3/epics/{epic-public-id}/comments 581 | * @secure 582 | */ 583 | listEpicComments = (epicPublicId: number, params: RequestParams = {}) => 584 | this.request({ 585 | path: `/api/v3/epics/${epicPublicId}/comments`, 586 | method: "GET", 587 | secure: true, 588 | format: "json", 589 | ...params, 590 | }); 591 | /** 592 | * @description This endpoint allows you to create a threaded Comment on an Epic. 593 | * 594 | * @name CreateEpicComment 595 | * @summary Create Epic Comment 596 | * @request POST:/api/v3/epics/{epic-public-id}/comments 597 | * @secure 598 | */ 599 | createEpicComment = ( 600 | epicPublicId: number, 601 | CreateEpicComment: CreateEpicComment, 602 | params: RequestParams = {}, 603 | ) => 604 | this.request({ 605 | path: `/api/v3/epics/${epicPublicId}/comments`, 606 | method: "POST", 607 | body: CreateEpicComment, 608 | secure: true, 609 | type: ContentType.Json, 610 | format: "json", 611 | ...params, 612 | }); 613 | /** 614 | * @description This endpoint allows you to create a nested Comment reply to an existing Epic Comment. 615 | * 616 | * @name CreateEpicCommentComment 617 | * @summary Create Epic Comment Comment 618 | * @request POST:/api/v3/epics/{epic-public-id}/comments/{comment-public-id} 619 | * @secure 620 | */ 621 | createEpicCommentComment = ( 622 | epicPublicId: number, 623 | commentPublicId: number, 624 | CreateCommentComment: CreateCommentComment, 625 | params: RequestParams = {}, 626 | ) => 627 | this.request({ 628 | path: `/api/v3/epics/${epicPublicId}/comments/${commentPublicId}`, 629 | method: "POST", 630 | body: CreateCommentComment, 631 | secure: true, 632 | type: ContentType.Json, 633 | format: "json", 634 | ...params, 635 | }); 636 | /** 637 | * @description This endpoint returns information about the selected Epic Comment. 638 | * 639 | * @name GetEpicComment 640 | * @summary Get Epic Comment 641 | * @request GET:/api/v3/epics/{epic-public-id}/comments/{comment-public-id} 642 | * @secure 643 | */ 644 | getEpicComment = ( 645 | epicPublicId: number, 646 | commentPublicId: number, 647 | params: RequestParams = {}, 648 | ) => 649 | this.request({ 650 | path: `/api/v3/epics/${epicPublicId}/comments/${commentPublicId}`, 651 | method: "GET", 652 | secure: true, 653 | format: "json", 654 | ...params, 655 | }); 656 | /** 657 | * @description This endpoint allows you to update a threaded Comment on an Epic. 658 | * 659 | * @name UpdateEpicComment 660 | * @summary Update Epic Comment 661 | * @request PUT:/api/v3/epics/{epic-public-id}/comments/{comment-public-id} 662 | * @secure 663 | */ 664 | updateEpicComment = ( 665 | epicPublicId: number, 666 | commentPublicId: number, 667 | UpdateComment: UpdateComment, 668 | params: RequestParams = {}, 669 | ) => 670 | this.request({ 671 | path: `/api/v3/epics/${epicPublicId}/comments/${commentPublicId}`, 672 | method: "PUT", 673 | body: UpdateComment, 674 | secure: true, 675 | type: ContentType.Json, 676 | format: "json", 677 | ...params, 678 | }); 679 | /** 680 | * @description This endpoint allows you to delete a Comment from an Epic. 681 | * 682 | * @name DeleteEpicComment 683 | * @summary Delete Epic Comment 684 | * @request DELETE:/api/v3/epics/{epic-public-id}/comments/{comment-public-id} 685 | * @secure 686 | */ 687 | deleteEpicComment = ( 688 | epicPublicId: number, 689 | commentPublicId: number, 690 | params: RequestParams = {}, 691 | ) => 692 | this.request({ 693 | path: `/api/v3/epics/${epicPublicId}/comments/${commentPublicId}`, 694 | method: "DELETE", 695 | secure: true, 696 | ...params, 697 | }); 698 | /** 699 | * @description Get the current health for the specified Epic. 700 | * 701 | * @name GetEpicHealth 702 | * @summary Get Epic Health 703 | * @request GET:/api/v3/epics/{epic-public-id}/health 704 | * @secure 705 | */ 706 | getEpicHealth = (epicPublicId: number, params: RequestParams = {}) => 707 | this.request({ 708 | path: `/api/v3/epics/${epicPublicId}/health`, 709 | method: "GET", 710 | secure: true, 711 | format: "json", 712 | ...params, 713 | }); 714 | /** 715 | * @description Create a new health status for the specified Epic. 716 | * 717 | * @name CreateEpicHealth 718 | * @summary Create Epic Health 719 | * @request POST:/api/v3/epics/{epic-public-id}/health 720 | * @secure 721 | */ 722 | createEpicHealth = ( 723 | epicPublicId: number, 724 | CreateEpicHealth: CreateEpicHealth, 725 | params: RequestParams = {}, 726 | ) => 727 | this.request({ 728 | path: `/api/v3/epics/${epicPublicId}/health`, 729 | method: "POST", 730 | body: CreateEpicHealth, 731 | secure: true, 732 | type: ContentType.Json, 733 | format: "json", 734 | ...params, 735 | }); 736 | /** 737 | * @description List the history of health statuses for the specified Epic, most recent first. 738 | * 739 | * @name ListEpicHealths 740 | * @summary List Epic Healths 741 | * @request GET:/api/v3/epics/{epic-public-id}/health-history 742 | * @secure 743 | */ 744 | listEpicHealths = (epicPublicId: number, params: RequestParams = {}) => 745 | this.request({ 746 | path: `/api/v3/epics/${epicPublicId}/health-history`, 747 | method: "GET", 748 | secure: true, 749 | format: "json", 750 | ...params, 751 | }); 752 | /** 753 | * @description Get a list of all Stories in an Epic. 754 | * 755 | * @name ListEpicStories 756 | * @summary List Epic Stories 757 | * @request GET:/api/v3/epics/{epic-public-id}/stories 758 | * @secure 759 | */ 760 | listEpicStories = ( 761 | epicPublicId: number, 762 | query?: { 763 | /** A true/false boolean indicating whether to return Stories with their descriptions. */ 764 | includes_description?: boolean; 765 | }, 766 | params: RequestParams = {}, 767 | ) => 768 | this.request({ 769 | path: `/api/v3/epics/${epicPublicId}/stories`, 770 | method: "GET", 771 | query: query, 772 | secure: true, 773 | format: "json", 774 | ...params, 775 | }); 776 | /** 777 | * @description This endpoint allows you to unlink a productboard epic. 778 | * 779 | * @name UnlinkProductboardFromEpic 780 | * @summary Unlink Productboard from Epic 781 | * @request POST:/api/v3/epics/{epic-public-id}/unlink-productboard 782 | * @secure 783 | */ 784 | unlinkProductboardFromEpic = ( 785 | epicPublicId: number, 786 | params: RequestParams = {}, 787 | ) => 788 | this.request({ 789 | path: `/api/v3/epics/${epicPublicId}/unlink-productboard`, 790 | method: "POST", 791 | secure: true, 792 | ...params, 793 | }); 794 | /** 795 | * @description Get Stories which have a given External Link associated with them. 796 | * 797 | * @name GetExternalLinkStories 798 | * @summary Get External Link Stories 799 | * @request GET:/api/v3/external-link/stories 800 | * @secure 801 | */ 802 | getExternalLinkStories = ( 803 | query: { 804 | /** 805 | * The external link associated with one or more stories. 806 | * @maxLength 2048 807 | * @pattern ^https?://.+$ 808 | */ 809 | external_link: string; 810 | }, 811 | params: RequestParams = {}, 812 | ) => 813 | this.request({ 814 | path: `/api/v3/external-link/stories`, 815 | method: "GET", 816 | query: query, 817 | secure: true, 818 | format: "json", 819 | ...params, 820 | }); 821 | /** 822 | * @description List Files returns a list of all UploadedFiles in the workspace. 823 | * 824 | * @name ListFiles 825 | * @summary List Files 826 | * @request GET:/api/v3/files 827 | * @secure 828 | */ 829 | listFiles = (params: RequestParams = {}) => 830 | this.request({ 831 | path: `/api/v3/files`, 832 | method: "GET", 833 | secure: true, 834 | format: "json", 835 | ...params, 836 | }); 837 | /** 838 | * @description Upload Files uploads one or many files and optionally associates them with a story. Use the multipart/form-data content-type to upload. Each `file` key should contain a separate file. Each UploadedFile's name comes from the Content-Disposition header "filename" directive for that field. 839 | * 840 | * @name UploadFiles 841 | * @summary Upload Files 842 | * @request POST:/api/v3/files 843 | * @secure 844 | */ 845 | uploadFiles = ( 846 | data: { 847 | /** 848 | * The story ID that these files will be associated with. 849 | * @format int64 850 | */ 851 | story_id?: number; 852 | /** 853 | * A file upload. At least one is required. 854 | * @format binary 855 | */ 856 | file0: File; 857 | /** 858 | * Optional additional files. 859 | * @format binary 860 | */ 861 | file1?: File; 862 | /** 863 | * Optional additional files. 864 | * @format binary 865 | */ 866 | file2?: File; 867 | /** 868 | * Optional additional files. 869 | * @format binary 870 | */ 871 | file3?: File; 872 | }, 873 | params: RequestParams = {}, 874 | ) => 875 | this.request({ 876 | path: `/api/v3/files`, 877 | method: "POST", 878 | body: data, 879 | secure: true, 880 | type: ContentType.FormData, 881 | format: "json", 882 | ...params, 883 | }); 884 | /** 885 | * @description Get File returns information about the selected UploadedFile. 886 | * 887 | * @name GetFile 888 | * @summary Get File 889 | * @request GET:/api/v3/files/{file-public-id} 890 | * @secure 891 | */ 892 | getFile = (filePublicId: number, params: RequestParams = {}) => 893 | this.request({ 894 | path: `/api/v3/files/${filePublicId}`, 895 | method: "GET", 896 | secure: true, 897 | format: "json", 898 | ...params, 899 | }); 900 | /** 901 | * @description Update File updates the properties of an UploadedFile (but not its content). 902 | * 903 | * @name UpdateFile 904 | * @summary Update File 905 | * @request PUT:/api/v3/files/{file-public-id} 906 | * @secure 907 | */ 908 | updateFile = ( 909 | filePublicId: number, 910 | UpdateFile: UpdateFile, 911 | params: RequestParams = {}, 912 | ) => 913 | this.request({ 914 | path: `/api/v3/files/${filePublicId}`, 915 | method: "PUT", 916 | body: UpdateFile, 917 | secure: true, 918 | type: ContentType.Json, 919 | format: "json", 920 | ...params, 921 | }); 922 | /** 923 | * @description Delete File deletes a previously uploaded file. 924 | * 925 | * @name DeleteFile 926 | * @summary Delete File 927 | * @request DELETE:/api/v3/files/{file-public-id} 928 | * @secure 929 | */ 930 | deleteFile = (filePublicId: number, params: RequestParams = {}) => 931 | this.request({ 932 | path: `/api/v3/files/${filePublicId}`, 933 | method: "DELETE", 934 | secure: true, 935 | ...params, 936 | }); 937 | /** 938 | * @description A group in our API maps to a "Team" within the Shortcut Product. A Team is a collection of Users that can be associated to Stories, Epics, and Iterations within Shortcut. 939 | * 940 | * @name ListGroups 941 | * @summary List Groups 942 | * @request GET:/api/v3/groups 943 | * @secure 944 | */ 945 | listGroups = (params: RequestParams = {}) => 946 | this.request({ 947 | path: `/api/v3/groups`, 948 | method: "GET", 949 | secure: true, 950 | format: "json", 951 | ...params, 952 | }); 953 | /** 954 | * No description 955 | * 956 | * @name CreateGroup 957 | * @summary Create Group 958 | * @request POST:/api/v3/groups 959 | * @secure 960 | */ 961 | createGroup = (CreateGroup: CreateGroup, params: RequestParams = {}) => 962 | this.request({ 963 | path: `/api/v3/groups`, 964 | method: "POST", 965 | body: CreateGroup, 966 | secure: true, 967 | type: ContentType.Json, 968 | format: "json", 969 | ...params, 970 | }); 971 | /** 972 | * No description 973 | * 974 | * @name GetGroup 975 | * @summary Get Group 976 | * @request GET:/api/v3/groups/{group-public-id} 977 | * @secure 978 | */ 979 | getGroup = (groupPublicId: string, params: RequestParams = {}) => 980 | this.request({ 981 | path: `/api/v3/groups/${groupPublicId}`, 982 | method: "GET", 983 | secure: true, 984 | format: "json", 985 | ...params, 986 | }); 987 | /** 988 | * No description 989 | * 990 | * @name UpdateGroup 991 | * @summary Update Group 992 | * @request PUT:/api/v3/groups/{group-public-id} 993 | * @secure 994 | */ 995 | updateGroup = ( 996 | groupPublicId: string, 997 | UpdateGroup: UpdateGroup, 998 | params: RequestParams = {}, 999 | ) => 1000 | this.request({ 1001 | path: `/api/v3/groups/${groupPublicId}`, 1002 | method: "PUT", 1003 | body: UpdateGroup, 1004 | secure: true, 1005 | type: ContentType.Json, 1006 | format: "json", 1007 | ...params, 1008 | }); 1009 | /** 1010 | * @description List the Stories assigned to the Group. (By default, limited to 1,000). 1011 | * 1012 | * @name ListGroupStories 1013 | * @summary List Group Stories 1014 | * @request GET:/api/v3/groups/{group-public-id}/stories 1015 | * @secure 1016 | */ 1017 | listGroupStories = ( 1018 | groupPublicId: string, 1019 | query?: { 1020 | /** 1021 | * The maximum number of results to return. (Defaults to 1000, max 1000) 1022 | * @format int64 1023 | */ 1024 | limit?: number; 1025 | /** 1026 | * The offset at which to begin returning results. (Defaults to 0) 1027 | * @format int64 1028 | */ 1029 | offset?: number; 1030 | }, 1031 | params: RequestParams = {}, 1032 | ) => 1033 | this.request({ 1034 | path: `/api/v3/groups/${groupPublicId}/stories`, 1035 | method: "GET", 1036 | query: query, 1037 | secure: true, 1038 | format: "json", 1039 | ...params, 1040 | }); 1041 | /** 1042 | * @description Update an existing health status by its ID. 1043 | * 1044 | * @name UpdateHealth 1045 | * @summary Update Health 1046 | * @request PUT:/api/v3/health/{health-public-id} 1047 | * @secure 1048 | */ 1049 | updateHealth = ( 1050 | healthPublicId: string, 1051 | UpdateHealth: UpdateHealth, 1052 | params: RequestParams = {}, 1053 | ) => 1054 | this.request({ 1055 | path: `/api/v3/health/${healthPublicId}`, 1056 | method: "PUT", 1057 | body: UpdateHealth, 1058 | secure: true, 1059 | type: ContentType.Json, 1060 | format: "json", 1061 | ...params, 1062 | }); 1063 | /** 1064 | * No description 1065 | * 1066 | * @name CreateGenericIntegration 1067 | * @summary Create Generic Integration 1068 | * @request POST:/api/v3/integrations/webhook 1069 | * @secure 1070 | */ 1071 | createGenericIntegration = ( 1072 | CreateGenericIntegration: CreateGenericIntegration, 1073 | params: RequestParams = {}, 1074 | ) => 1075 | this.request({ 1076 | path: `/api/v3/integrations/webhook`, 1077 | method: "POST", 1078 | body: CreateGenericIntegration, 1079 | secure: true, 1080 | type: ContentType.Json, 1081 | ...params, 1082 | }); 1083 | /** 1084 | * No description 1085 | * 1086 | * @name GetGenericIntegration 1087 | * @summary Get Generic Integration 1088 | * @request GET:/api/v3/integrations/webhook/{integration-public-id} 1089 | * @secure 1090 | */ 1091 | getGenericIntegration = ( 1092 | integrationPublicId: number, 1093 | params: RequestParams = {}, 1094 | ) => 1095 | this.request({ 1096 | path: `/api/v3/integrations/webhook/${integrationPublicId}`, 1097 | method: "GET", 1098 | secure: true, 1099 | ...params, 1100 | }); 1101 | /** 1102 | * No description 1103 | * 1104 | * @name DeleteGenericIntegration 1105 | * @summary Delete Generic Integration 1106 | * @request DELETE:/api/v3/integrations/webhook/{integration-public-id} 1107 | * @secure 1108 | */ 1109 | deleteGenericIntegration = ( 1110 | integrationPublicId: number, 1111 | params: RequestParams = {}, 1112 | ) => 1113 | this.request({ 1114 | path: `/api/v3/integrations/webhook/${integrationPublicId}`, 1115 | method: "DELETE", 1116 | secure: true, 1117 | ...params, 1118 | }); 1119 | /** 1120 | * No description 1121 | * 1122 | * @name ListIterations 1123 | * @summary List Iterations 1124 | * @request GET:/api/v3/iterations 1125 | * @secure 1126 | */ 1127 | listIterations = (params: RequestParams = {}) => 1128 | this.request({ 1129 | path: `/api/v3/iterations`, 1130 | method: "GET", 1131 | secure: true, 1132 | format: "json", 1133 | ...params, 1134 | }); 1135 | /** 1136 | * No description 1137 | * 1138 | * @name CreateIteration 1139 | * @summary Create Iteration 1140 | * @request POST:/api/v3/iterations 1141 | * @secure 1142 | */ 1143 | createIteration = ( 1144 | CreateIteration: CreateIteration, 1145 | params: RequestParams = {}, 1146 | ) => 1147 | this.request({ 1148 | path: `/api/v3/iterations`, 1149 | method: "POST", 1150 | body: CreateIteration, 1151 | secure: true, 1152 | type: ContentType.Json, 1153 | format: "json", 1154 | ...params, 1155 | }); 1156 | /** 1157 | * @description Disables Iterations for the current workspace 1158 | * 1159 | * @name DisableIterations 1160 | * @summary Disable Iterations 1161 | * @request PUT:/api/v3/iterations/disable 1162 | * @secure 1163 | */ 1164 | disableIterations = (params: RequestParams = {}) => 1165 | this.request({ 1166 | path: `/api/v3/iterations/disable`, 1167 | method: "PUT", 1168 | secure: true, 1169 | ...params, 1170 | }); 1171 | /** 1172 | * @description Enables Iterations for the current workspace 1173 | * 1174 | * @name EnableIterations 1175 | * @summary Enable Iterations 1176 | * @request PUT:/api/v3/iterations/enable 1177 | * @secure 1178 | */ 1179 | enableIterations = (params: RequestParams = {}) => 1180 | this.request({ 1181 | path: `/api/v3/iterations/enable`, 1182 | method: "PUT", 1183 | secure: true, 1184 | ...params, 1185 | }); 1186 | /** 1187 | * No description 1188 | * 1189 | * @name GetIteration 1190 | * @summary Get Iteration 1191 | * @request GET:/api/v3/iterations/{iteration-public-id} 1192 | * @secure 1193 | */ 1194 | getIteration = (iterationPublicId: number, params: RequestParams = {}) => 1195 | this.request({ 1196 | path: `/api/v3/iterations/${iterationPublicId}`, 1197 | method: "GET", 1198 | secure: true, 1199 | format: "json", 1200 | ...params, 1201 | }); 1202 | /** 1203 | * No description 1204 | * 1205 | * @name UpdateIteration 1206 | * @summary Update Iteration 1207 | * @request PUT:/api/v3/iterations/{iteration-public-id} 1208 | * @secure 1209 | */ 1210 | updateIteration = ( 1211 | iterationPublicId: number, 1212 | UpdateIteration: UpdateIteration, 1213 | params: RequestParams = {}, 1214 | ) => 1215 | this.request({ 1216 | path: `/api/v3/iterations/${iterationPublicId}`, 1217 | method: "PUT", 1218 | body: UpdateIteration, 1219 | secure: true, 1220 | type: ContentType.Json, 1221 | format: "json", 1222 | ...params, 1223 | }); 1224 | /** 1225 | * No description 1226 | * 1227 | * @name DeleteIteration 1228 | * @summary Delete Iteration 1229 | * @request DELETE:/api/v3/iterations/{iteration-public-id} 1230 | * @secure 1231 | */ 1232 | deleteIteration = (iterationPublicId: number, params: RequestParams = {}) => 1233 | this.request({ 1234 | path: `/api/v3/iterations/${iterationPublicId}`, 1235 | method: "DELETE", 1236 | secure: true, 1237 | ...params, 1238 | }); 1239 | /** 1240 | * @description Get a list of all Stories in an Iteration. 1241 | * 1242 | * @name ListIterationStories 1243 | * @summary List Iteration Stories 1244 | * @request GET:/api/v3/iterations/{iteration-public-id}/stories 1245 | * @secure 1246 | */ 1247 | listIterationStories = ( 1248 | iterationPublicId: number, 1249 | query?: { 1250 | /** A true/false boolean indicating whether to return Stories with their descriptions. */ 1251 | includes_description?: boolean; 1252 | }, 1253 | params: RequestParams = {}, 1254 | ) => 1255 | this.request({ 1256 | path: `/api/v3/iterations/${iterationPublicId}/stories`, 1257 | method: "GET", 1258 | query: query, 1259 | secure: true, 1260 | format: "json", 1261 | ...params, 1262 | }); 1263 | /** 1264 | * @description Get Key Result returns information about a chosen Key Result. 1265 | * 1266 | * @name GetKeyResult 1267 | * @summary Get Key Result 1268 | * @request GET:/api/v3/key-results/{key-result-public-id} 1269 | * @secure 1270 | */ 1271 | getKeyResult = (keyResultPublicId: string, params: RequestParams = {}) => 1272 | this.request({ 1273 | path: `/api/v3/key-results/${keyResultPublicId}`, 1274 | method: "GET", 1275 | secure: true, 1276 | format: "json", 1277 | ...params, 1278 | }); 1279 | /** 1280 | * @description Update Key Result allows updating a Key Result's name or initial, observed, or target values. 1281 | * 1282 | * @name UpdateKeyResult 1283 | * @summary Update Key Result 1284 | * @request PUT:/api/v3/key-results/{key-result-public-id} 1285 | * @secure 1286 | */ 1287 | updateKeyResult = ( 1288 | keyResultPublicId: string, 1289 | UpdateKeyResult: UpdateKeyResult, 1290 | params: RequestParams = {}, 1291 | ) => 1292 | this.request({ 1293 | path: `/api/v3/key-results/${keyResultPublicId}`, 1294 | method: "PUT", 1295 | body: UpdateKeyResult, 1296 | secure: true, 1297 | type: ContentType.Json, 1298 | format: "json", 1299 | ...params, 1300 | }); 1301 | /** 1302 | * @description List Labels returns a list of all Labels and their attributes. 1303 | * 1304 | * @name ListLabels 1305 | * @summary List Labels 1306 | * @request GET:/api/v3/labels 1307 | * @secure 1308 | */ 1309 | listLabels = ( 1310 | query?: { 1311 | /** A true/false boolean indicating if the slim versions of the Label should be returned. */ 1312 | slim?: boolean; 1313 | }, 1314 | params: RequestParams = {}, 1315 | ) => 1316 | this.request({ 1317 | path: `/api/v3/labels`, 1318 | method: "GET", 1319 | query: query, 1320 | secure: true, 1321 | format: "json", 1322 | ...params, 1323 | }); 1324 | /** 1325 | * @description Create Label allows you to create a new Label in Shortcut. 1326 | * 1327 | * @name CreateLabel 1328 | * @summary Create Label 1329 | * @request POST:/api/v3/labels 1330 | * @secure 1331 | */ 1332 | createLabel = ( 1333 | CreateLabelParams: CreateLabelParams, 1334 | params: RequestParams = {}, 1335 | ) => 1336 | this.request({ 1337 | path: `/api/v3/labels`, 1338 | method: "POST", 1339 | body: CreateLabelParams, 1340 | secure: true, 1341 | type: ContentType.Json, 1342 | format: "json", 1343 | ...params, 1344 | }); 1345 | /** 1346 | * @description Get Label returns information about the selected Label. 1347 | * 1348 | * @name GetLabel 1349 | * @summary Get Label 1350 | * @request GET:/api/v3/labels/{label-public-id} 1351 | * @secure 1352 | */ 1353 | getLabel = (labelPublicId: number, params: RequestParams = {}) => 1354 | this.request({ 1355 | path: `/api/v3/labels/${labelPublicId}`, 1356 | method: "GET", 1357 | secure: true, 1358 | format: "json", 1359 | ...params, 1360 | }); 1361 | /** 1362 | * @description Update Label allows you to replace a Label name with another name. If you try to name a Label something that already exists, you will receive a 422 response. 1363 | * 1364 | * @name UpdateLabel 1365 | * @summary Update Label 1366 | * @request PUT:/api/v3/labels/{label-public-id} 1367 | * @secure 1368 | */ 1369 | updateLabel = ( 1370 | labelPublicId: number, 1371 | UpdateLabel: UpdateLabel, 1372 | params: RequestParams = {}, 1373 | ) => 1374 | this.request({ 1375 | path: `/api/v3/labels/${labelPublicId}`, 1376 | method: "PUT", 1377 | body: UpdateLabel, 1378 | secure: true, 1379 | type: ContentType.Json, 1380 | format: "json", 1381 | ...params, 1382 | }); 1383 | /** 1384 | * @description Delete Label can be used to delete any Label. 1385 | * 1386 | * @name DeleteLabel 1387 | * @summary Delete Label 1388 | * @request DELETE:/api/v3/labels/{label-public-id} 1389 | * @secure 1390 | */ 1391 | deleteLabel = (labelPublicId: number, params: RequestParams = {}) => 1392 | this.request({ 1393 | path: `/api/v3/labels/${labelPublicId}`, 1394 | method: "DELETE", 1395 | secure: true, 1396 | ...params, 1397 | }); 1398 | /** 1399 | * @description List all of the Epics with the Label. 1400 | * 1401 | * @name ListLabelEpics 1402 | * @summary List Label Epics 1403 | * @request GET:/api/v3/labels/{label-public-id}/epics 1404 | * @secure 1405 | */ 1406 | listLabelEpics = (labelPublicId: number, params: RequestParams = {}) => 1407 | this.request({ 1408 | path: `/api/v3/labels/${labelPublicId}/epics`, 1409 | method: "GET", 1410 | secure: true, 1411 | format: "json", 1412 | ...params, 1413 | }); 1414 | /** 1415 | * @description List all of the Stories with the Label. 1416 | * 1417 | * @name ListLabelStories 1418 | * @summary List Label Stories 1419 | * @request GET:/api/v3/labels/{label-public-id}/stories 1420 | * @secure 1421 | */ 1422 | listLabelStories = ( 1423 | labelPublicId: number, 1424 | query?: { 1425 | /** A true/false boolean indicating whether to return Stories with their descriptions. */ 1426 | includes_description?: boolean; 1427 | }, 1428 | params: RequestParams = {}, 1429 | ) => 1430 | this.request({ 1431 | path: `/api/v3/labels/${labelPublicId}/stories`, 1432 | method: "GET", 1433 | query: query, 1434 | secure: true, 1435 | format: "json", 1436 | ...params, 1437 | }); 1438 | /** 1439 | * @description List Linked Files returns a list of all Linked-Files and their attributes. 1440 | * 1441 | * @name ListLinkedFiles 1442 | * @summary List Linked Files 1443 | * @request GET:/api/v3/linked-files 1444 | * @secure 1445 | */ 1446 | listLinkedFiles = (params: RequestParams = {}) => 1447 | this.request({ 1448 | path: `/api/v3/linked-files`, 1449 | method: "GET", 1450 | secure: true, 1451 | format: "json", 1452 | ...params, 1453 | }); 1454 | /** 1455 | * @description Create Linked File allows you to create a new Linked File in Shortcut. 1456 | * 1457 | * @name CreateLinkedFile 1458 | * @summary Create Linked File 1459 | * @request POST:/api/v3/linked-files 1460 | * @secure 1461 | */ 1462 | createLinkedFile = ( 1463 | CreateLinkedFile: CreateLinkedFile, 1464 | params: RequestParams = {}, 1465 | ) => 1466 | this.request({ 1467 | path: `/api/v3/linked-files`, 1468 | method: "POST", 1469 | body: CreateLinkedFile, 1470 | secure: true, 1471 | type: ContentType.Json, 1472 | format: "json", 1473 | ...params, 1474 | }); 1475 | /** 1476 | * @description Get File returns information about the selected Linked File. 1477 | * 1478 | * @name GetLinkedFile 1479 | * @summary Get Linked File 1480 | * @request GET:/api/v3/linked-files/{linked-file-public-id} 1481 | * @secure 1482 | */ 1483 | getLinkedFile = (linkedFilePublicId: number, params: RequestParams = {}) => 1484 | this.request({ 1485 | path: `/api/v3/linked-files/${linkedFilePublicId}`, 1486 | method: "GET", 1487 | secure: true, 1488 | format: "json", 1489 | ...params, 1490 | }); 1491 | /** 1492 | * @description Updated Linked File allows you to update properties of a previously attached Linked-File. 1493 | * 1494 | * @name UpdateLinkedFile 1495 | * @summary Update Linked File 1496 | * @request PUT:/api/v3/linked-files/{linked-file-public-id} 1497 | * @secure 1498 | */ 1499 | updateLinkedFile = ( 1500 | linkedFilePublicId: number, 1501 | UpdateLinkedFile: UpdateLinkedFile, 1502 | params: RequestParams = {}, 1503 | ) => 1504 | this.request({ 1505 | path: `/api/v3/linked-files/${linkedFilePublicId}`, 1506 | method: "PUT", 1507 | body: UpdateLinkedFile, 1508 | secure: true, 1509 | type: ContentType.Json, 1510 | format: "json", 1511 | ...params, 1512 | }); 1513 | /** 1514 | * @description Delete Linked File can be used to delete any previously attached Linked-File. 1515 | * 1516 | * @name DeleteLinkedFile 1517 | * @summary Delete Linked File 1518 | * @request DELETE:/api/v3/linked-files/{linked-file-public-id} 1519 | * @secure 1520 | */ 1521 | deleteLinkedFile = (linkedFilePublicId: number, params: RequestParams = {}) => 1522 | this.request({ 1523 | path: `/api/v3/linked-files/${linkedFilePublicId}`, 1524 | method: "DELETE", 1525 | secure: true, 1526 | ...params, 1527 | }); 1528 | /** 1529 | * @description Returns information about the authenticated member. 1530 | * 1531 | * @name GetCurrentMemberInfo 1532 | * @summary Get Current Member Info 1533 | * @request GET:/api/v3/member 1534 | * @secure 1535 | */ 1536 | getCurrentMemberInfo = (params: RequestParams = {}) => 1537 | this.request({ 1538 | path: `/api/v3/member`, 1539 | method: "GET", 1540 | secure: true, 1541 | format: "json", 1542 | ...params, 1543 | }); 1544 | /** 1545 | * @description Returns information about members of the Workspace. 1546 | * 1547 | * @name ListMembers 1548 | * @summary List Members 1549 | * @request GET:/api/v3/members 1550 | * @secure 1551 | */ 1552 | listMembers = ( 1553 | query?: { 1554 | /** 1555 | * The unique ID of the Organization to limit the list to. 1556 | * @format uuid 1557 | */ 1558 | "org-public-id"?: string; 1559 | /** Filter members by their disabled state. If true, return only disabled members. If false, return only enabled members. */ 1560 | disabled?: boolean; 1561 | }, 1562 | params: RequestParams = {}, 1563 | ) => 1564 | this.request({ 1565 | path: `/api/v3/members`, 1566 | method: "GET", 1567 | query: query, 1568 | secure: true, 1569 | format: "json", 1570 | ...params, 1571 | }); 1572 | /** 1573 | * @description Returns information about a Member. 1574 | * 1575 | * @name GetMember 1576 | * @summary Get Member 1577 | * @request GET:/api/v3/members/{member-public-id} 1578 | * @secure 1579 | */ 1580 | getMember = ( 1581 | memberPublicId: string, 1582 | query?: { 1583 | /** 1584 | * The unique ID of the Organization to limit the lookup to. 1585 | * @format uuid 1586 | */ 1587 | "org-public-id"?: string; 1588 | }, 1589 | params: RequestParams = {}, 1590 | ) => 1591 | this.request({ 1592 | path: `/api/v3/members/${memberPublicId}`, 1593 | method: "GET", 1594 | query: query, 1595 | secure: true, 1596 | format: "json", 1597 | ...params, 1598 | }); 1599 | /** 1600 | * @description (Deprecated: Use 'List Objectives') List Milestones returns a list of all Milestones and their attributes. 1601 | * 1602 | * @name ListMilestones 1603 | * @summary List Milestones 1604 | * @request GET:/api/v3/milestones 1605 | * @secure 1606 | */ 1607 | listMilestones = (params: RequestParams = {}) => 1608 | this.request({ 1609 | path: `/api/v3/milestones`, 1610 | method: "GET", 1611 | secure: true, 1612 | format: "json", 1613 | ...params, 1614 | }); 1615 | /** 1616 | * @description (Deprecated: Use 'Create Objective') Create Milestone allows you to create a new Milestone in Shortcut. 1617 | * 1618 | * @name CreateMilestone 1619 | * @summary Create Milestone 1620 | * @request POST:/api/v3/milestones 1621 | * @secure 1622 | */ 1623 | createMilestone = ( 1624 | CreateMilestone: CreateMilestone, 1625 | params: RequestParams = {}, 1626 | ) => 1627 | this.request({ 1628 | path: `/api/v3/milestones`, 1629 | method: "POST", 1630 | body: CreateMilestone, 1631 | secure: true, 1632 | type: ContentType.Json, 1633 | format: "json", 1634 | ...params, 1635 | }); 1636 | /** 1637 | * @description (Deprecated: Use 'Get Objective') Get Milestone returns information about a chosen Milestone. 1638 | * 1639 | * @name GetMilestone 1640 | * @summary Get Milestone 1641 | * @request GET:/api/v3/milestones/{milestone-public-id} 1642 | * @secure 1643 | */ 1644 | getMilestone = (milestonePublicId: number, params: RequestParams = {}) => 1645 | this.request({ 1646 | path: `/api/v3/milestones/${milestonePublicId}`, 1647 | method: "GET", 1648 | secure: true, 1649 | format: "json", 1650 | ...params, 1651 | }); 1652 | /** 1653 | * @description (Deprecated: Use 'Update Objective') Update Milestone can be used to update Milestone properties. 1654 | * 1655 | * @name UpdateMilestone 1656 | * @summary Update Milestone 1657 | * @request PUT:/api/v3/milestones/{milestone-public-id} 1658 | * @secure 1659 | */ 1660 | updateMilestone = ( 1661 | milestonePublicId: number, 1662 | UpdateMilestone: UpdateMilestone, 1663 | params: RequestParams = {}, 1664 | ) => 1665 | this.request({ 1666 | path: `/api/v3/milestones/${milestonePublicId}`, 1667 | method: "PUT", 1668 | body: UpdateMilestone, 1669 | secure: true, 1670 | type: ContentType.Json, 1671 | format: "json", 1672 | ...params, 1673 | }); 1674 | /** 1675 | * @description (Deprecated: Use 'Delete Objective') Delete Milestone can be used to delete any Milestone. 1676 | * 1677 | * @name DeleteMilestone 1678 | * @summary Delete Milestone 1679 | * @request DELETE:/api/v3/milestones/{milestone-public-id} 1680 | * @secure 1681 | */ 1682 | deleteMilestone = (milestonePublicId: number, params: RequestParams = {}) => 1683 | this.request({ 1684 | path: `/api/v3/milestones/${milestonePublicId}`, 1685 | method: "DELETE", 1686 | secure: true, 1687 | ...params, 1688 | }); 1689 | /** 1690 | * @description (Deprecated: Use 'List Objective Epics') List all of the Epics within the Milestone. 1691 | * 1692 | * @name ListMilestoneEpics 1693 | * @summary List Milestone Epics 1694 | * @request GET:/api/v3/milestones/{milestone-public-id}/epics 1695 | * @secure 1696 | */ 1697 | listMilestoneEpics = ( 1698 | milestonePublicId: number, 1699 | params: RequestParams = {}, 1700 | ) => 1701 | this.request({ 1702 | path: `/api/v3/milestones/${milestonePublicId}/epics`, 1703 | method: "GET", 1704 | secure: true, 1705 | format: "json", 1706 | ...params, 1707 | }); 1708 | /** 1709 | * @description List Objectives returns a list of all Objectives and their attributes. 1710 | * 1711 | * @name ListObjectives 1712 | * @summary List Objectives 1713 | * @request GET:/api/v3/objectives 1714 | * @secure 1715 | */ 1716 | listObjectives = (params: RequestParams = {}) => 1717 | this.request({ 1718 | path: `/api/v3/objectives`, 1719 | method: "GET", 1720 | secure: true, 1721 | format: "json", 1722 | ...params, 1723 | }); 1724 | /** 1725 | * @description Create Objective allows you to create a new Objective in Shortcut. 1726 | * 1727 | * @name CreateObjective 1728 | * @summary Create Objective 1729 | * @request POST:/api/v3/objectives 1730 | * @secure 1731 | */ 1732 | createObjective = ( 1733 | CreateObjective: CreateObjective, 1734 | params: RequestParams = {}, 1735 | ) => 1736 | this.request({ 1737 | path: `/api/v3/objectives`, 1738 | method: "POST", 1739 | body: CreateObjective, 1740 | secure: true, 1741 | type: ContentType.Json, 1742 | format: "json", 1743 | ...params, 1744 | }); 1745 | /** 1746 | * @description Get Objective returns information about a chosen Objective. 1747 | * 1748 | * @name GetObjective 1749 | * @summary Get Objective 1750 | * @request GET:/api/v3/objectives/{objective-public-id} 1751 | * @secure 1752 | */ 1753 | getObjective = (objectivePublicId: number, params: RequestParams = {}) => 1754 | this.request({ 1755 | path: `/api/v3/objectives/${objectivePublicId}`, 1756 | method: "GET", 1757 | secure: true, 1758 | format: "json", 1759 | ...params, 1760 | }); 1761 | /** 1762 | * @description Update Objective can be used to update Objective properties. 1763 | * 1764 | * @name UpdateObjective 1765 | * @summary Update Objective 1766 | * @request PUT:/api/v3/objectives/{objective-public-id} 1767 | * @secure 1768 | */ 1769 | updateObjective = ( 1770 | objectivePublicId: number, 1771 | UpdateObjective: UpdateObjective, 1772 | params: RequestParams = {}, 1773 | ) => 1774 | this.request({ 1775 | path: `/api/v3/objectives/${objectivePublicId}`, 1776 | method: "PUT", 1777 | body: UpdateObjective, 1778 | secure: true, 1779 | type: ContentType.Json, 1780 | format: "json", 1781 | ...params, 1782 | }); 1783 | /** 1784 | * @description Delete Objective can be used to delete any Objective. 1785 | * 1786 | * @name DeleteObjective 1787 | * @summary Delete Objective 1788 | * @request DELETE:/api/v3/objectives/{objective-public-id} 1789 | * @secure 1790 | */ 1791 | deleteObjective = (objectivePublicId: number, params: RequestParams = {}) => 1792 | this.request({ 1793 | path: `/api/v3/objectives/${objectivePublicId}`, 1794 | method: "DELETE", 1795 | secure: true, 1796 | ...params, 1797 | }); 1798 | /** 1799 | * @description List all of the Epics within the Objective. 1800 | * 1801 | * @name ListObjectiveEpics 1802 | * @summary List Objective Epics 1803 | * @request GET:/api/v3/objectives/{objective-public-id}/epics 1804 | * @secure 1805 | */ 1806 | listObjectiveEpics = ( 1807 | objectivePublicId: number, 1808 | params: RequestParams = {}, 1809 | ) => 1810 | this.request({ 1811 | path: `/api/v3/objectives/${objectivePublicId}/epics`, 1812 | method: "GET", 1813 | secure: true, 1814 | format: "json", 1815 | ...params, 1816 | }); 1817 | /** 1818 | * @description List Projects returns a list of all Projects and their attributes. 1819 | * 1820 | * @name ListProjects 1821 | * @summary List Projects 1822 | * @request GET:/api/v3/projects 1823 | * @secure 1824 | */ 1825 | listProjects = (params: RequestParams = {}) => 1826 | this.request({ 1827 | path: `/api/v3/projects`, 1828 | method: "GET", 1829 | secure: true, 1830 | format: "json", 1831 | ...params, 1832 | }); 1833 | /** 1834 | * @description Create Project is used to create a new Shortcut Project. 1835 | * 1836 | * @name CreateProject 1837 | * @summary Create Project 1838 | * @request POST:/api/v3/projects 1839 | * @secure 1840 | */ 1841 | createProject = (CreateProject: CreateProject, params: RequestParams = {}) => 1842 | this.request({ 1843 | path: `/api/v3/projects`, 1844 | method: "POST", 1845 | body: CreateProject, 1846 | secure: true, 1847 | type: ContentType.Json, 1848 | format: "json", 1849 | ...params, 1850 | }); 1851 | /** 1852 | * @description Get Project returns information about the selected Project. 1853 | * 1854 | * @name GetProject 1855 | * @summary Get Project 1856 | * @request GET:/api/v3/projects/{project-public-id} 1857 | * @secure 1858 | */ 1859 | getProject = (projectPublicId: number, params: RequestParams = {}) => 1860 | this.request({ 1861 | path: `/api/v3/projects/${projectPublicId}`, 1862 | method: "GET", 1863 | secure: true, 1864 | format: "json", 1865 | ...params, 1866 | }); 1867 | /** 1868 | * @description Update Project can be used to change properties of a Project. 1869 | * 1870 | * @name UpdateProject 1871 | * @summary Update Project 1872 | * @request PUT:/api/v3/projects/{project-public-id} 1873 | * @secure 1874 | */ 1875 | updateProject = ( 1876 | projectPublicId: number, 1877 | UpdateProject: UpdateProject, 1878 | params: RequestParams = {}, 1879 | ) => 1880 | this.request({ 1881 | path: `/api/v3/projects/${projectPublicId}`, 1882 | method: "PUT", 1883 | body: UpdateProject, 1884 | secure: true, 1885 | type: ContentType.Json, 1886 | format: "json", 1887 | ...params, 1888 | }); 1889 | /** 1890 | * @description Delete Project can be used to delete a Project. Projects can only be deleted if all associated Stories are moved or deleted. In the case that the Project cannot be deleted, you will receive a 422 response. 1891 | * 1892 | * @name DeleteProject 1893 | * @summary Delete Project 1894 | * @request DELETE:/api/v3/projects/{project-public-id} 1895 | * @secure 1896 | */ 1897 | deleteProject = (projectPublicId: number, params: RequestParams = {}) => 1898 | this.request({ 1899 | path: `/api/v3/projects/${projectPublicId}`, 1900 | method: "DELETE", 1901 | secure: true, 1902 | ...params, 1903 | }); 1904 | /** 1905 | * @description List Stories returns a list of all Stories in a selected Project and their attributes. 1906 | * 1907 | * @name ListStories 1908 | * @summary List Stories 1909 | * @request GET:/api/v3/projects/{project-public-id}/stories 1910 | * @secure 1911 | */ 1912 | listStories = ( 1913 | projectPublicId: number, 1914 | query?: { 1915 | /** A true/false boolean indicating whether to return Stories with their descriptions. */ 1916 | includes_description?: boolean; 1917 | }, 1918 | params: RequestParams = {}, 1919 | ) => 1920 | this.request({ 1921 | path: `/api/v3/projects/${projectPublicId}/stories`, 1922 | method: "GET", 1923 | query: query, 1924 | secure: true, 1925 | format: "json", 1926 | ...params, 1927 | }); 1928 | /** 1929 | * @description List Repositories returns a list of all Repositories and their attributes. 1930 | * 1931 | * @name ListRepositories 1932 | * @summary List Repositories 1933 | * @request GET:/api/v3/repositories 1934 | * @secure 1935 | */ 1936 | listRepositories = (params: RequestParams = {}) => 1937 | this.request({ 1938 | path: `/api/v3/repositories`, 1939 | method: "GET", 1940 | secure: true, 1941 | format: "json", 1942 | ...params, 1943 | }); 1944 | /** 1945 | * @description Get Repository returns information about the selected Repository. 1946 | * 1947 | * @name GetRepository 1948 | * @summary Get Repository 1949 | * @request GET:/api/v3/repositories/{repo-public-id} 1950 | * @secure 1951 | */ 1952 | getRepository = (repoPublicId: number, params: RequestParams = {}) => 1953 | this.request({ 1954 | path: `/api/v3/repositories/${repoPublicId}`, 1955 | method: "GET", 1956 | secure: true, 1957 | format: "json", 1958 | ...params, 1959 | }); 1960 | /** 1961 | * @description Search lets you search Epics and Stories based on desired parameters. Since ordering of the results can change over time (due to search ranking decay, new Epics and Stories being created), the `next` value from the previous response can be used as the path and query string for the next page to ensure stable ordering. 1962 | * 1963 | * @name Search 1964 | * @summary Search 1965 | * @request GET:/api/v3/search 1966 | * @secure 1967 | */ 1968 | search = ( 1969 | query: { 1970 | /** 1971 | * See our help center article on [search operators](https://help.shortcut.com/hc/en-us/articles/360000046646-Search-Operators) 1972 | * @minLength 1 1973 | */ 1974 | query: string; 1975 | /** 1976 | * The number of search results to include in a page. Minimum of 1 and maximum of 250. 1977 | * @format int64 1978 | */ 1979 | page_size?: number; 1980 | /** 1981 | * The amount of detail included in each result item. 1982 | * "full" will include all descriptions and comments and more fields on 1983 | * related items such as pull requests, branches and tasks. 1984 | * "slim" omits larger fulltext fields such as descriptions and comments 1985 | * and only references related items by id. 1986 | * The default is "full". 1987 | */ 1988 | detail?: "full" | "slim"; 1989 | /** The next page token. */ 1990 | next?: string; 1991 | /** A collection of entity_types to search. Defaults to story and epic. Supports: epic, iteration, objective, story. */ 1992 | entity_types?: ( 1993 | | "story" 1994 | | "milestone" 1995 | | "epic" 1996 | | "iteration" 1997 | | "objective" 1998 | )[]; 1999 | }, 2000 | params: RequestParams = {}, 2001 | ) => 2002 | this.request({ 2003 | path: `/api/v3/search`, 2004 | method: "GET", 2005 | query: query, 2006 | secure: true, 2007 | format: "json", 2008 | ...params, 2009 | }); 2010 | /** 2011 | * @description Search Epics lets you search Epics based on desired parameters. Since ordering of stories can change over time (due to search ranking decay, new Epics being created), the `next` value from the previous response can be used as the path and query string for the next page to ensure stable ordering. 2012 | * 2013 | * @name SearchEpics 2014 | * @summary Search Epics 2015 | * @request GET:/api/v3/search/epics 2016 | * @secure 2017 | */ 2018 | searchEpics = ( 2019 | query: { 2020 | /** 2021 | * See our help center article on [search operators](https://help.shortcut.com/hc/en-us/articles/360000046646-Search-Operators) 2022 | * @minLength 1 2023 | */ 2024 | query: string; 2025 | /** 2026 | * The number of search results to include in a page. Minimum of 1 and maximum of 250. 2027 | * @format int64 2028 | */ 2029 | page_size?: number; 2030 | /** 2031 | * The amount of detail included in each result item. 2032 | * "full" will include all descriptions and comments and more fields on 2033 | * related items such as pull requests, branches and tasks. 2034 | * "slim" omits larger fulltext fields such as descriptions and comments 2035 | * and only references related items by id. 2036 | * The default is "full". 2037 | */ 2038 | detail?: "full" | "slim"; 2039 | /** The next page token. */ 2040 | next?: string; 2041 | /** A collection of entity_types to search. Defaults to story and epic. Supports: epic, iteration, objective, story. */ 2042 | entity_types?: ( 2043 | | "story" 2044 | | "milestone" 2045 | | "epic" 2046 | | "iteration" 2047 | | "objective" 2048 | )[]; 2049 | }, 2050 | params: RequestParams = {}, 2051 | ) => 2052 | this.request({ 2053 | path: `/api/v3/search/epics`, 2054 | method: "GET", 2055 | query: query, 2056 | secure: true, 2057 | format: "json", 2058 | ...params, 2059 | }); 2060 | /** 2061 | * @description Search Iterations lets you search Iterations based on desired parameters. Since ordering of results can change over time (due to search ranking decay, new Iterations being created), the `next` value from the previous response can be used as the path and query string for the next page to ensure stable ordering. 2062 | * 2063 | * @name SearchIterations 2064 | * @summary Search Iterations 2065 | * @request GET:/api/v3/search/iterations 2066 | * @secure 2067 | */ 2068 | searchIterations = ( 2069 | query: { 2070 | /** 2071 | * See our help center article on [search operators](https://help.shortcut.com/hc/en-us/articles/360000046646-Search-Operators) 2072 | * @minLength 1 2073 | */ 2074 | query: string; 2075 | /** 2076 | * The number of search results to include in a page. Minimum of 1 and maximum of 250. 2077 | * @format int64 2078 | */ 2079 | page_size?: number; 2080 | /** 2081 | * The amount of detail included in each result item. 2082 | * "full" will include all descriptions and comments and more fields on 2083 | * related items such as pull requests, branches and tasks. 2084 | * "slim" omits larger fulltext fields such as descriptions and comments 2085 | * and only references related items by id. 2086 | * The default is "full". 2087 | */ 2088 | detail?: "full" | "slim"; 2089 | /** The next page token. */ 2090 | next?: string; 2091 | /** A collection of entity_types to search. Defaults to story and epic. Supports: epic, iteration, objective, story. */ 2092 | entity_types?: ( 2093 | | "story" 2094 | | "milestone" 2095 | | "epic" 2096 | | "iteration" 2097 | | "objective" 2098 | )[]; 2099 | }, 2100 | params: RequestParams = {}, 2101 | ) => 2102 | this.request({ 2103 | path: `/api/v3/search/iterations`, 2104 | method: "GET", 2105 | query: query, 2106 | secure: true, 2107 | format: "json", 2108 | ...params, 2109 | }); 2110 | /** 2111 | * @description Search Milestones lets you search Milestones based on desired parameters. Since ordering of results can change over time (due to search ranking decay, new Milestones being created), the `next` value from the previous response can be used as the path and query string for the next page to ensure stable ordering. 2112 | * 2113 | * @name SearchMilestones 2114 | * @summary Search Milestones 2115 | * @request GET:/api/v3/search/milestones 2116 | * @secure 2117 | */ 2118 | searchMilestones = ( 2119 | query: { 2120 | /** 2121 | * See our help center article on [search operators](https://help.shortcut.com/hc/en-us/articles/360000046646-Search-Operators) 2122 | * @minLength 1 2123 | */ 2124 | query: string; 2125 | /** 2126 | * The number of search results to include in a page. Minimum of 1 and maximum of 250. 2127 | * @format int64 2128 | */ 2129 | page_size?: number; 2130 | /** 2131 | * The amount of detail included in each result item. 2132 | * "full" will include all descriptions and comments and more fields on 2133 | * related items such as pull requests, branches and tasks. 2134 | * "slim" omits larger fulltext fields such as descriptions and comments 2135 | * and only references related items by id. 2136 | * The default is "full". 2137 | */ 2138 | detail?: "full" | "slim"; 2139 | /** The next page token. */ 2140 | next?: string; 2141 | /** A collection of entity_types to search. Defaults to story and epic. Supports: epic, iteration, objective, story. */ 2142 | entity_types?: ( 2143 | | "story" 2144 | | "milestone" 2145 | | "epic" 2146 | | "iteration" 2147 | | "objective" 2148 | )[]; 2149 | }, 2150 | params: RequestParams = {}, 2151 | ) => 2152 | this.request({ 2153 | path: `/api/v3/search/milestones`, 2154 | method: "GET", 2155 | query: query, 2156 | secure: true, 2157 | format: "json", 2158 | ...params, 2159 | }); 2160 | /** 2161 | * @description Search Objectives lets you search Objectives based on desired parameters. Since ordering of results can change over time (due to search ranking decay, new Objectives being created), the `next` value from the previous response can be used as the path and query string for the next page to ensure stable ordering. 2162 | * 2163 | * @name SearchObjectives 2164 | * @summary Search Objectives 2165 | * @request GET:/api/v3/search/objectives 2166 | * @secure 2167 | */ 2168 | searchObjectives = ( 2169 | query: { 2170 | /** 2171 | * See our help center article on [search operators](https://help.shortcut.com/hc/en-us/articles/360000046646-Search-Operators) 2172 | * @minLength 1 2173 | */ 2174 | query: string; 2175 | /** 2176 | * The number of search results to include in a page. Minimum of 1 and maximum of 250. 2177 | * @format int64 2178 | */ 2179 | page_size?: number; 2180 | /** 2181 | * The amount of detail included in each result item. 2182 | * "full" will include all descriptions and comments and more fields on 2183 | * related items such as pull requests, branches and tasks. 2184 | * "slim" omits larger fulltext fields such as descriptions and comments 2185 | * and only references related items by id. 2186 | * The default is "full". 2187 | */ 2188 | detail?: "full" | "slim"; 2189 | /** The next page token. */ 2190 | next?: string; 2191 | /** A collection of entity_types to search. Defaults to story and epic. Supports: epic, iteration, objective, story. */ 2192 | entity_types?: ( 2193 | | "story" 2194 | | "milestone" 2195 | | "epic" 2196 | | "iteration" 2197 | | "objective" 2198 | )[]; 2199 | }, 2200 | params: RequestParams = {}, 2201 | ) => 2202 | this.request({ 2203 | path: `/api/v3/search/objectives`, 2204 | method: "GET", 2205 | query: query, 2206 | secure: true, 2207 | format: "json", 2208 | ...params, 2209 | }); 2210 | /** 2211 | * @description Search Stories lets you search Stories based on desired parameters. Since ordering of stories can change over time (due to search ranking decay, new stories being created), the `next` value from the previous response can be used as the path and query string for the next page to ensure stable ordering. 2212 | * 2213 | * @name SearchStories 2214 | * @summary Search Stories 2215 | * @request GET:/api/v3/search/stories 2216 | * @secure 2217 | */ 2218 | searchStories = ( 2219 | query: { 2220 | /** 2221 | * See our help center article on [search operators](https://help.shortcut.com/hc/en-us/articles/360000046646-Search-Operators) 2222 | * @minLength 1 2223 | */ 2224 | query: string; 2225 | /** 2226 | * The number of search results to include in a page. Minimum of 1 and maximum of 250. 2227 | * @format int64 2228 | */ 2229 | page_size?: number; 2230 | /** 2231 | * The amount of detail included in each result item. 2232 | * "full" will include all descriptions and comments and more fields on 2233 | * related items such as pull requests, branches and tasks. 2234 | * "slim" omits larger fulltext fields such as descriptions and comments 2235 | * and only references related items by id. 2236 | * The default is "full". 2237 | */ 2238 | detail?: "full" | "slim"; 2239 | /** The next page token. */ 2240 | next?: string; 2241 | /** A collection of entity_types to search. Defaults to story and epic. Supports: epic, iteration, objective, story. */ 2242 | entity_types?: ( 2243 | | "story" 2244 | | "milestone" 2245 | | "epic" 2246 | | "iteration" 2247 | | "objective" 2248 | )[]; 2249 | }, 2250 | params: RequestParams = {}, 2251 | ) => 2252 | this.request({ 2253 | path: `/api/v3/search/stories`, 2254 | method: "GET", 2255 | query: query, 2256 | secure: true, 2257 | format: "json", 2258 | ...params, 2259 | }); 2260 | /** 2261 | * @description Create Story is used to add a new story to your Shortcut Workspace. This endpoint requires that either **workflow_state_id** or **project_id** be provided, but will reject the request if both or neither are specified. The workflow_state_id has been marked as required and is the recommended field to specify because we are in the process of sunsetting Projects in Shortcut. 2262 | * 2263 | * @name CreateStory 2264 | * @summary Create Story 2265 | * @request POST:/api/v3/stories 2266 | * @secure 2267 | */ 2268 | createStory = ( 2269 | CreateStoryParams: CreateStoryParams, 2270 | params: RequestParams = {}, 2271 | ) => 2272 | this.request({ 2273 | path: `/api/v3/stories`, 2274 | method: "POST", 2275 | body: CreateStoryParams, 2276 | secure: true, 2277 | type: ContentType.Json, 2278 | format: "json", 2279 | ...params, 2280 | }); 2281 | /** 2282 | * @description Create Multiple Stories allows you to create multiple stories in a single request using the same syntax as [Create Story](https://developer.shortcut.com/api/rest/v3#create-story). 2283 | * 2284 | * @name CreateMultipleStories 2285 | * @summary Create Multiple Stories 2286 | * @request POST:/api/v3/stories/bulk 2287 | * @secure 2288 | */ 2289 | createMultipleStories = ( 2290 | CreateStories: CreateStories, 2291 | params: RequestParams = {}, 2292 | ) => 2293 | this.request({ 2294 | path: `/api/v3/stories/bulk`, 2295 | method: "POST", 2296 | body: CreateStories, 2297 | secure: true, 2298 | type: ContentType.Json, 2299 | format: "json", 2300 | ...params, 2301 | }); 2302 | /** 2303 | * @description Update Multiple Stories allows you to make changes to numerous stories at once. 2304 | * 2305 | * @name UpdateMultipleStories 2306 | * @summary Update Multiple Stories 2307 | * @request PUT:/api/v3/stories/bulk 2308 | * @secure 2309 | */ 2310 | updateMultipleStories = ( 2311 | UpdateStories: UpdateStories, 2312 | params: RequestParams = {}, 2313 | ) => 2314 | this.request({ 2315 | path: `/api/v3/stories/bulk`, 2316 | method: "PUT", 2317 | body: UpdateStories, 2318 | secure: true, 2319 | type: ContentType.Json, 2320 | format: "json", 2321 | ...params, 2322 | }); 2323 | /** 2324 | * @description Delete Multiple Stories allows you to delete multiple archived stories at once. 2325 | * 2326 | * @name DeleteMultipleStories 2327 | * @summary Delete Multiple Stories 2328 | * @request DELETE:/api/v3/stories/bulk 2329 | * @secure 2330 | */ 2331 | deleteMultipleStories = ( 2332 | DeleteStories: DeleteStories, 2333 | params: RequestParams = {}, 2334 | ) => 2335 | this.request({ 2336 | path: `/api/v3/stories/bulk`, 2337 | method: "DELETE", 2338 | body: DeleteStories, 2339 | secure: true, 2340 | type: ContentType.Json, 2341 | ...params, 2342 | }); 2343 | /** 2344 | * @description Create Story From Template is used to add a new story derived from a template to your Shortcut Workspace. 2345 | * 2346 | * @name CreateStoryFromTemplate 2347 | * @summary Create Story From Template 2348 | * @request POST:/api/v3/stories/from-template 2349 | * @secure 2350 | */ 2351 | createStoryFromTemplate = ( 2352 | CreateStoryFromTemplateParams: CreateStoryFromTemplateParams, 2353 | params: RequestParams = {}, 2354 | ) => 2355 | this.request({ 2356 | path: `/api/v3/stories/from-template`, 2357 | method: "POST", 2358 | body: CreateStoryFromTemplateParams, 2359 | secure: true, 2360 | type: ContentType.Json, 2361 | format: "json", 2362 | ...params, 2363 | }); 2364 | /** 2365 | * @description Search Stories lets you search Stories based on desired parameters. 2366 | * 2367 | * @name SearchStoriesOld 2368 | * @summary Search Stories (Old) 2369 | * @request POST:/api/v3/stories/search 2370 | * @secure 2371 | */ 2372 | searchStoriesOld = ( 2373 | SearchStories: SearchStories, 2374 | params: RequestParams = {}, 2375 | ) => 2376 | this.request({ 2377 | path: `/api/v3/stories/search`, 2378 | method: "POST", 2379 | body: SearchStories, 2380 | secure: true, 2381 | type: ContentType.Json, 2382 | format: "json", 2383 | ...params, 2384 | }); 2385 | /** 2386 | * @description Get Story returns information about a chosen Story. 2387 | * 2388 | * @name GetStory 2389 | * @summary Get Story 2390 | * @request GET:/api/v3/stories/{story-public-id} 2391 | * @secure 2392 | */ 2393 | getStory = (storyPublicId: number, params: RequestParams = {}) => 2394 | this.request({ 2395 | path: `/api/v3/stories/${storyPublicId}`, 2396 | method: "GET", 2397 | secure: true, 2398 | format: "json", 2399 | ...params, 2400 | }); 2401 | /** 2402 | * @description Update Story can be used to update Story properties. 2403 | * 2404 | * @name UpdateStory 2405 | * @summary Update Story 2406 | * @request PUT:/api/v3/stories/{story-public-id} 2407 | * @secure 2408 | */ 2409 | updateStory = ( 2410 | storyPublicId: number, 2411 | UpdateStory: UpdateStory, 2412 | params: RequestParams = {}, 2413 | ) => 2414 | this.request({ 2415 | path: `/api/v3/stories/${storyPublicId}`, 2416 | method: "PUT", 2417 | body: UpdateStory, 2418 | secure: true, 2419 | type: ContentType.Json, 2420 | format: "json", 2421 | ...params, 2422 | }); 2423 | /** 2424 | * @description Delete Story can be used to delete any Story. 2425 | * 2426 | * @name DeleteStory 2427 | * @summary Delete Story 2428 | * @request DELETE:/api/v3/stories/{story-public-id} 2429 | * @secure 2430 | */ 2431 | deleteStory = (storyPublicId: number, params: RequestParams = {}) => 2432 | this.request({ 2433 | path: `/api/v3/stories/${storyPublicId}`, 2434 | method: "DELETE", 2435 | secure: true, 2436 | ...params, 2437 | }); 2438 | /** 2439 | * @description Lists Comments associated with a Story 2440 | * 2441 | * @name ListStoryComment 2442 | * @summary List Story Comment 2443 | * @request GET:/api/v3/stories/{story-public-id}/comments 2444 | * @secure 2445 | */ 2446 | listStoryComment = (storyPublicId: number, params: RequestParams = {}) => 2447 | this.request({ 2448 | path: `/api/v3/stories/${storyPublicId}/comments`, 2449 | method: "GET", 2450 | secure: true, 2451 | format: "json", 2452 | ...params, 2453 | }); 2454 | /** 2455 | * @description Create Comment allows you to create a Comment on any Story. 2456 | * 2457 | * @name CreateStoryComment 2458 | * @summary Create Story Comment 2459 | * @request POST:/api/v3/stories/{story-public-id}/comments 2460 | * @secure 2461 | */ 2462 | createStoryComment = ( 2463 | storyPublicId: number, 2464 | CreateStoryComment: CreateStoryComment, 2465 | params: RequestParams = {}, 2466 | ) => 2467 | this.request({ 2468 | path: `/api/v3/stories/${storyPublicId}/comments`, 2469 | method: "POST", 2470 | body: CreateStoryComment, 2471 | secure: true, 2472 | type: ContentType.Json, 2473 | format: "json", 2474 | ...params, 2475 | }); 2476 | /** 2477 | * @description Get Comment is used to get Comment information. 2478 | * 2479 | * @name GetStoryComment 2480 | * @summary Get Story Comment 2481 | * @request GET:/api/v3/stories/{story-public-id}/comments/{comment-public-id} 2482 | * @secure 2483 | */ 2484 | getStoryComment = ( 2485 | storyPublicId: number, 2486 | commentPublicId: number, 2487 | params: RequestParams = {}, 2488 | ) => 2489 | this.request({ 2490 | path: `/api/v3/stories/${storyPublicId}/comments/${commentPublicId}`, 2491 | method: "GET", 2492 | secure: true, 2493 | format: "json", 2494 | ...params, 2495 | }); 2496 | /** 2497 | * @description Update Comment replaces the text of the existing Comment. 2498 | * 2499 | * @name UpdateStoryComment 2500 | * @summary Update Story Comment 2501 | * @request PUT:/api/v3/stories/{story-public-id}/comments/{comment-public-id} 2502 | * @secure 2503 | */ 2504 | updateStoryComment = ( 2505 | storyPublicId: number, 2506 | commentPublicId: number, 2507 | UpdateStoryComment: UpdateStoryComment, 2508 | params: RequestParams = {}, 2509 | ) => 2510 | this.request({ 2511 | path: `/api/v3/stories/${storyPublicId}/comments/${commentPublicId}`, 2512 | method: "PUT", 2513 | body: UpdateStoryComment, 2514 | secure: true, 2515 | type: ContentType.Json, 2516 | format: "json", 2517 | ...params, 2518 | }); 2519 | /** 2520 | * @description Delete a Comment from any story. 2521 | * 2522 | * @name DeleteStoryComment 2523 | * @summary Delete Story Comment 2524 | * @request DELETE:/api/v3/stories/{story-public-id}/comments/{comment-public-id} 2525 | * @secure 2526 | */ 2527 | deleteStoryComment = ( 2528 | storyPublicId: number, 2529 | commentPublicId: number, 2530 | params: RequestParams = {}, 2531 | ) => 2532 | this.request({ 2533 | path: `/api/v3/stories/${storyPublicId}/comments/${commentPublicId}`, 2534 | method: "DELETE", 2535 | secure: true, 2536 | ...params, 2537 | }); 2538 | /** 2539 | * @description Create a reaction to a story comment. 2540 | * 2541 | * @name CreateStoryReaction 2542 | * @summary Create Story Reaction 2543 | * @request POST:/api/v3/stories/{story-public-id}/comments/{comment-public-id}/reactions 2544 | * @secure 2545 | */ 2546 | createStoryReaction = ( 2547 | storyPublicId: number, 2548 | commentPublicId: number, 2549 | CreateOrDeleteStoryReaction: CreateOrDeleteStoryReaction, 2550 | params: RequestParams = {}, 2551 | ) => 2552 | this.request({ 2553 | path: `/api/v3/stories/${storyPublicId}/comments/${commentPublicId}/reactions`, 2554 | method: "POST", 2555 | body: CreateOrDeleteStoryReaction, 2556 | secure: true, 2557 | type: ContentType.Json, 2558 | format: "json", 2559 | ...params, 2560 | }); 2561 | /** 2562 | * @description Delete a reaction from any story comment. 2563 | * 2564 | * @name DeleteStoryReaction 2565 | * @summary Delete Story Reaction 2566 | * @request DELETE:/api/v3/stories/{story-public-id}/comments/{comment-public-id}/reactions 2567 | * @secure 2568 | */ 2569 | deleteStoryReaction = ( 2570 | storyPublicId: number, 2571 | commentPublicId: number, 2572 | CreateOrDeleteStoryReaction: CreateOrDeleteStoryReaction, 2573 | params: RequestParams = {}, 2574 | ) => 2575 | this.request({ 2576 | path: `/api/v3/stories/${storyPublicId}/comments/${commentPublicId}/reactions`, 2577 | method: "DELETE", 2578 | body: CreateOrDeleteStoryReaction, 2579 | secure: true, 2580 | type: ContentType.Json, 2581 | ...params, 2582 | }); 2583 | /** 2584 | * @description Unlinks a Comment from its linked Slack thread (Comment replies and Slack replies will no longer be synced) 2585 | * 2586 | * @name UnlinkCommentThreadFromSlack 2587 | * @summary Unlink Comment thread from Slack 2588 | * @request POST:/api/v3/stories/{story-public-id}/comments/{comment-public-id}/unlink-from-slack 2589 | * @secure 2590 | */ 2591 | unlinkCommentThreadFromSlack = ( 2592 | storyPublicId: number, 2593 | commentPublicId: number, 2594 | params: RequestParams = {}, 2595 | ) => 2596 | this.request({ 2597 | path: `/api/v3/stories/${storyPublicId}/comments/${commentPublicId}/unlink-from-slack`, 2598 | method: "POST", 2599 | secure: true, 2600 | format: "json", 2601 | ...params, 2602 | }); 2603 | /** 2604 | * No description 2605 | * 2606 | * @name StoryHistory 2607 | * @summary Story History 2608 | * @request GET:/api/v3/stories/{story-public-id}/history 2609 | * @secure 2610 | */ 2611 | storyHistory = (storyPublicId: number, params: RequestParams = {}) => 2612 | this.request({ 2613 | path: `/api/v3/stories/${storyPublicId}/history`, 2614 | method: "GET", 2615 | secure: true, 2616 | format: "json", 2617 | ...params, 2618 | }); 2619 | /** 2620 | * @description Create Task is used to create a new task in a Story. 2621 | * 2622 | * @name CreateTask 2623 | * @summary Create Task 2624 | * @request POST:/api/v3/stories/{story-public-id}/tasks 2625 | * @secure 2626 | */ 2627 | createTask = ( 2628 | storyPublicId: number, 2629 | CreateTask: CreateTask, 2630 | params: RequestParams = {}, 2631 | ) => 2632 | this.request({ 2633 | path: `/api/v3/stories/${storyPublicId}/tasks`, 2634 | method: "POST", 2635 | body: CreateTask, 2636 | secure: true, 2637 | type: ContentType.Json, 2638 | format: "json", 2639 | ...params, 2640 | }); 2641 | /** 2642 | * @description Returns information about a chosen Task. 2643 | * 2644 | * @name GetTask 2645 | * @summary Get Task 2646 | * @request GET:/api/v3/stories/{story-public-id}/tasks/{task-public-id} 2647 | * @secure 2648 | */ 2649 | getTask = ( 2650 | storyPublicId: number, 2651 | taskPublicId: number, 2652 | params: RequestParams = {}, 2653 | ) => 2654 | this.request({ 2655 | path: `/api/v3/stories/${storyPublicId}/tasks/${taskPublicId}`, 2656 | method: "GET", 2657 | secure: true, 2658 | format: "json", 2659 | ...params, 2660 | }); 2661 | /** 2662 | * @description Update Task can be used to update Task properties. 2663 | * 2664 | * @name UpdateTask 2665 | * @summary Update Task 2666 | * @request PUT:/api/v3/stories/{story-public-id}/tasks/{task-public-id} 2667 | * @secure 2668 | */ 2669 | updateTask = ( 2670 | storyPublicId: number, 2671 | taskPublicId: number, 2672 | UpdateTask: UpdateTask, 2673 | params: RequestParams = {}, 2674 | ) => 2675 | this.request({ 2676 | path: `/api/v3/stories/${storyPublicId}/tasks/${taskPublicId}`, 2677 | method: "PUT", 2678 | body: UpdateTask, 2679 | secure: true, 2680 | type: ContentType.Json, 2681 | format: "json", 2682 | ...params, 2683 | }); 2684 | /** 2685 | * @description Delete Task can be used to delete any previously created Task on a Story. 2686 | * 2687 | * @name DeleteTask 2688 | * @summary Delete Task 2689 | * @request DELETE:/api/v3/stories/{story-public-id}/tasks/{task-public-id} 2690 | * @secure 2691 | */ 2692 | deleteTask = ( 2693 | storyPublicId: number, 2694 | taskPublicId: number, 2695 | params: RequestParams = {}, 2696 | ) => 2697 | this.request({ 2698 | path: `/api/v3/stories/${storyPublicId}/tasks/${taskPublicId}`, 2699 | method: "DELETE", 2700 | secure: true, 2701 | ...params, 2702 | }); 2703 | /** 2704 | * @description Story Links (called Story Relationships in the UI) allow you create semantic relationships between two stories. The parameters read like an active voice grammatical sentence: subject -> verb -> object. The subject story acts on the object Story; the object story is the direct object of the sentence. The subject story "blocks", "duplicates", or "relates to" the object story. Examples: - "story 5 blocks story 6” -- story 6 is now "blocked" until story 5 is moved to a Done workflow state. - "story 2 duplicates story 1” -- Story 2 represents the same body of work as Story 1 (and should probably be archived). - "story 7 relates to story 3” 2705 | * 2706 | * @name CreateStoryLink 2707 | * @summary Create Story Link 2708 | * @request POST:/api/v3/story-links 2709 | * @secure 2710 | */ 2711 | createStoryLink = ( 2712 | CreateStoryLink: CreateStoryLink, 2713 | params: RequestParams = {}, 2714 | ) => 2715 | this.request({ 2716 | path: `/api/v3/story-links`, 2717 | method: "POST", 2718 | body: CreateStoryLink, 2719 | secure: true, 2720 | type: ContentType.Json, 2721 | format: "json", 2722 | ...params, 2723 | }); 2724 | /** 2725 | * @description Returns the stories and their relationship for the given Story Link. 2726 | * 2727 | * @name GetStoryLink 2728 | * @summary Get Story Link 2729 | * @request GET:/api/v3/story-links/{story-link-public-id} 2730 | * @secure 2731 | */ 2732 | getStoryLink = (storyLinkPublicId: number, params: RequestParams = {}) => 2733 | this.request({ 2734 | path: `/api/v3/story-links/${storyLinkPublicId}`, 2735 | method: "GET", 2736 | secure: true, 2737 | format: "json", 2738 | ...params, 2739 | }); 2740 | /** 2741 | * @description Updates the stories and/or the relationship for the given Story Link. 2742 | * 2743 | * @name UpdateStoryLink 2744 | * @summary Update Story Link 2745 | * @request PUT:/api/v3/story-links/{story-link-public-id} 2746 | * @secure 2747 | */ 2748 | updateStoryLink = ( 2749 | storyLinkPublicId: number, 2750 | UpdateStoryLink: UpdateStoryLink, 2751 | params: RequestParams = {}, 2752 | ) => 2753 | this.request({ 2754 | path: `/api/v3/story-links/${storyLinkPublicId}`, 2755 | method: "PUT", 2756 | body: UpdateStoryLink, 2757 | secure: true, 2758 | type: ContentType.Json, 2759 | format: "json", 2760 | ...params, 2761 | }); 2762 | /** 2763 | * @description Removes the relationship between the stories for the given Story Link. 2764 | * 2765 | * @name DeleteStoryLink 2766 | * @summary Delete Story Link 2767 | * @request DELETE:/api/v3/story-links/{story-link-public-id} 2768 | * @secure 2769 | */ 2770 | deleteStoryLink = (storyLinkPublicId: number, params: RequestParams = {}) => 2771 | this.request({ 2772 | path: `/api/v3/story-links/${storyLinkPublicId}`, 2773 | method: "DELETE", 2774 | secure: true, 2775 | ...params, 2776 | }); 2777 | /** 2778 | * @description Returns a list of all Workflows in the Workspace. 2779 | * 2780 | * @name ListWorkflows 2781 | * @summary List Workflows 2782 | * @request GET:/api/v3/workflows 2783 | * @secure 2784 | */ 2785 | listWorkflows = (params: RequestParams = {}) => 2786 | this.request({ 2787 | path: `/api/v3/workflows`, 2788 | method: "GET", 2789 | secure: true, 2790 | format: "json", 2791 | ...params, 2792 | }); 2793 | /** 2794 | * @description Get Workflow returns information about a chosen Workflow. 2795 | * 2796 | * @name GetWorkflow 2797 | * @summary Get Workflow 2798 | * @request GET:/api/v3/workflows/{workflow-public-id} 2799 | * @secure 2800 | */ 2801 | getWorkflow = (workflowPublicId: number, params: RequestParams = {}) => 2802 | this.request({ 2803 | path: `/api/v3/workflows/${workflowPublicId}`, 2804 | method: "GET", 2805 | secure: true, 2806 | format: "json", 2807 | ...params, 2808 | }); 2809 | } 2810 | -------------------------------------------------------------------------------- /src/generated/http-client.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-nocheck 4 | /* 5 | * --------------------------------------------------------------- 6 | * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## 7 | * ## ## 8 | * ## AUTHOR: acacode ## 9 | * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## 10 | * --------------------------------------------------------------- 11 | */ 12 | 13 | import type { 14 | AxiosInstance, 15 | AxiosRequestConfig, 16 | AxiosResponse, 17 | HeadersDefaults, 18 | ResponseType, 19 | } from "axios"; 20 | import axios from "axios"; 21 | 22 | export type QueryParamsType = Record; 23 | 24 | export interface FullRequestParams 25 | extends Omit { 26 | /** set parameter to `true` for call `securityWorker` for this request */ 27 | secure?: boolean; 28 | /** request path */ 29 | path: string; 30 | /** content type of request body */ 31 | type?: ContentType; 32 | /** query params */ 33 | query?: QueryParamsType; 34 | /** format of response (i.e. response.json() -> format: "json") */ 35 | format?: ResponseType; 36 | /** request body */ 37 | body?: unknown; 38 | } 39 | 40 | export type RequestParams = Omit< 41 | FullRequestParams, 42 | "body" | "method" | "query" | "path" 43 | >; 44 | 45 | export interface ApiConfig 46 | extends Omit { 47 | securityWorker?: ( 48 | securityData: SecurityDataType | null, 49 | ) => Promise | AxiosRequestConfig | void; 50 | secure?: boolean; 51 | format?: ResponseType; 52 | } 53 | 54 | export enum ContentType { 55 | Json = "application/json", 56 | FormData = "multipart/form-data", 57 | UrlEncoded = "application/x-www-form-urlencoded", 58 | Text = "text/plain", 59 | } 60 | 61 | /** 62 | * @internal 63 | * @private 64 | */ 65 | 66 | export class HttpClient { 67 | public instance: AxiosInstance; 68 | private securityData: SecurityDataType | null = null; 69 | private securityWorker?: ApiConfig["securityWorker"]; 70 | private secure?: boolean; 71 | private format?: ResponseType; 72 | 73 | constructor({ 74 | securityWorker, 75 | secure, 76 | format, 77 | ...axiosConfig 78 | }: ApiConfig = {}) { 79 | this.instance = axios.create({ 80 | ...axiosConfig, 81 | baseURL: axiosConfig.baseURL || "https://api.app.shortcut.com", 82 | }); 83 | this.secure = secure; 84 | this.format = format; 85 | this.securityWorker = securityWorker; 86 | } 87 | 88 | public setSecurityData = (data: SecurityDataType | null) => { 89 | this.securityData = data; 90 | }; 91 | 92 | protected mergeRequestParams( 93 | params1: AxiosRequestConfig, 94 | params2?: AxiosRequestConfig, 95 | ): AxiosRequestConfig { 96 | const method = params1.method || (params2 && params2.method); 97 | 98 | return { 99 | ...this.instance.defaults, 100 | ...params1, 101 | ...(params2 || {}), 102 | headers: { 103 | ...((method && 104 | this.instance.defaults.headers[ 105 | method.toLowerCase() as keyof HeadersDefaults 106 | ]) || 107 | {}), 108 | ...(params1.headers || {}), 109 | ...((params2 && params2.headers) || {}), 110 | }, 111 | }; 112 | } 113 | 114 | protected stringifyFormItem(formItem: unknown) { 115 | if (typeof formItem === "object" && formItem !== null) { 116 | return JSON.stringify(formItem); 117 | } else { 118 | return `${formItem}`; 119 | } 120 | } 121 | 122 | protected createFormData(input: Record): FormData { 123 | return Object.keys(input || {}).reduce((formData, key) => { 124 | const property = input[key]; 125 | const propertyContent: any[] = 126 | property instanceof Array ? property : [property]; 127 | 128 | for (const formItem of propertyContent) { 129 | const isFileType = formItem instanceof Blob; 130 | formData.append( 131 | key, 132 | isFileType ? formItem : this.stringifyFormItem(formItem), 133 | ); 134 | } 135 | 136 | return formData; 137 | }, new FormData()); 138 | } 139 | 140 | public request = async ({ 141 | secure, 142 | path, 143 | type, 144 | query, 145 | format, 146 | body, 147 | ...params 148 | }: FullRequestParams): Promise> => { 149 | const secureParams = 150 | ((typeof secure === "boolean" ? secure : this.secure) && 151 | this.securityWorker && 152 | (await this.securityWorker(this.securityData))) || 153 | {}; 154 | const requestParams = this.mergeRequestParams(params, secureParams); 155 | const responseFormat = format || this.format || undefined; 156 | 157 | if ( 158 | type === ContentType.FormData && 159 | body && 160 | body !== null && 161 | typeof body === "object" 162 | ) { 163 | body = this.createFormData(body as Record); 164 | } 165 | 166 | if ( 167 | type === ContentType.Text && 168 | body && 169 | body !== null && 170 | typeof body !== "string" 171 | ) { 172 | body = JSON.stringify(body); 173 | } 174 | 175 | return this.instance.request({ 176 | ...requestParams, 177 | headers: { 178 | ...(requestParams.headers || {}), 179 | ...(type && type !== ContentType.FormData 180 | ? { "Content-Type": type } 181 | : {}), 182 | }, 183 | params: query, 184 | responseType: responseFormat, 185 | data: body, 186 | url: path, 187 | }); 188 | }; 189 | } 190 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { ShortcutClient as default } from './ShortcutClient'; 2 | export * from './ShortcutClient'; 3 | export * from './generated/data-contracts'; 4 | -------------------------------------------------------------------------------- /src/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'stream-to-blob'; 2 | -------------------------------------------------------------------------------- /templates/http-client.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | const { apiConfig, generateResponses, config } = it; 3 | %> 4 | 5 | import type { AxiosInstance, AxiosRequestConfig, HeadersDefaults, ResponseType, AxiosResponse } from "axios"; 6 | import axios from "axios"; 7 | 8 | export type QueryParamsType = Record; 9 | 10 | export interface FullRequestParams extends Omit { 11 | /** set parameter to `true` for call `securityWorker` for this request */ 12 | secure?: boolean; 13 | /** request path */ 14 | path: string; 15 | /** content type of request body */ 16 | type?: ContentType; 17 | /** query params */ 18 | query?: QueryParamsType; 19 | /** format of response (i.e. response.json() -> format: "json") */ 20 | format?: ResponseType; 21 | /** request body */ 22 | body?: unknown; 23 | } 24 | 25 | export type RequestParams = Omit; 26 | 27 | export interface ApiConfig extends Omit { 28 | securityWorker?: (securityData: SecurityDataType | null) => Promise | AxiosRequestConfig | void; 29 | secure?: boolean; 30 | format?: ResponseType; 31 | } 32 | 33 | export enum ContentType { 34 | Json = "application/json", 35 | FormData = "multipart/form-data", 36 | UrlEncoded = "application/x-www-form-urlencoded", 37 | Text = "text/plain", 38 | } 39 | 40 | export class HttpClient { 41 | public instance: AxiosInstance; 42 | private securityData: SecurityDataType | null = null; 43 | private securityWorker?: ApiConfig["securityWorker"]; 44 | private secure?: boolean; 45 | private format?: ResponseType; 46 | 47 | constructor({ securityWorker, secure, format, ...axiosConfig }: ApiConfig = {}) { 48 | this.instance = axios.create({ ...axiosConfig, baseURL: axiosConfig.baseURL || "<%~ apiConfig.baseUrl %>" }) 49 | this.secure = secure; 50 | this.format = format; 51 | this.securityWorker = securityWorker; 52 | } 53 | 54 | public setSecurityData = (data: SecurityDataType | null) => { 55 | this.securityData = data 56 | } 57 | 58 | protected mergeRequestParams(params1: AxiosRequestConfig, params2?: AxiosRequestConfig): AxiosRequestConfig { 59 | const method = params1.method || (params2 && params2.method) 60 | 61 | return { 62 | ...this.instance.defaults, 63 | ...params1, 64 | ...(params2 || {}), 65 | headers: { 66 | ...((method && this.instance.defaults.headers[method.toLowerCase() as keyof HeadersDefaults]) || {}), 67 | ...(params1.headers || {}), 68 | ...((params2 && params2.headers) || {}), 69 | }, 70 | }; 71 | } 72 | 73 | protected stringifyFormItem(formItem: unknown) { 74 | if (typeof formItem === "object" && formItem !== null) { 75 | return JSON.stringify(formItem); 76 | } else { 77 | return `${formItem}`; 78 | } 79 | } 80 | 81 | protected createFormData(input: Record): FormData { 82 | return Object.keys(input || {}).reduce((formData, key) => { 83 | const property = input[key]; 84 | const propertyContent: any[] = (property instanceof Array) ? property : [property] 85 | 86 | for (const formItem of propertyContent) { 87 | const isFileType = formItem instanceof Blob; 88 | formData.append( 89 | key, 90 | isFileType ? formItem : this.stringifyFormItem(formItem) 91 | ); 92 | } 93 | 94 | return formData; 95 | }, new FormData()); 96 | } 97 | 98 | public request = async ({ 99 | secure, 100 | path, 101 | type, 102 | query, 103 | format, 104 | body, 105 | ...params 106 | <% if (config.unwrapResponseData) { %> 107 | }: FullRequestParams): Promise => { 108 | <% } else { %> 109 | }: FullRequestParams): Promise> => { 110 | <% } %> 111 | const secureParams = ((typeof secure === 'boolean' ? secure : this.secure) && this.securityWorker && (await this.securityWorker(this.securityData))) || {}; 112 | const requestParams = this.mergeRequestParams(params, secureParams); 113 | const responseFormat = (format || this.format) || undefined; 114 | 115 | if (type === ContentType.FormData && body && body !== null && typeof body === "object") { 116 | body = this.createFormData(body as Record); 117 | } 118 | 119 | if (type === ContentType.Text && body && body !== null && typeof body !== "string") { 120 | body = JSON.stringify(body); 121 | } 122 | 123 | return this.instance.request({ 124 | ...requestParams, 125 | headers: { 126 | ...(requestParams.headers || {}), 127 | ...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}), 128 | }, 129 | params: query, 130 | responseType: responseFormat, 131 | data: body, 132 | url: path, 133 | <% if (config.unwrapResponseData) { %> 134 | }).then(response => response.data); 135 | <% } else { %> 136 | }); 137 | <% } %> 138 | }; 139 | } 140 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@total-typescript/tsconfig/bundler/no-dom/library", 3 | "include": ["src"], 4 | "exclude": ["**/__tests__/**"], 5 | "ts-node": { 6 | "files": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | import { globSync } from 'glob'; 3 | 4 | export default defineConfig({ 5 | // Find all TypeScript files (excluding tests and type definitions) 6 | entry: globSync('src/**/*.ts', { 7 | ignore: ['src/**/__tests__/**', 'src/**/*.test.ts', 'src/**/*.d.ts'], 8 | }), 9 | outDir: 'lib', 10 | format: ['esm', 'cjs'], 11 | dts: true, 12 | clean: true, 13 | splitting: false, // Disable code splitting to maintain file structure 14 | }); 15 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "headings": { 3 | "readme": false 4 | } 5 | } 6 | --------------------------------------------------------------------------------