npm package: @studiohyperdrive/swagger-express-ts
Description: Typescript decorators to generate Swagger docs.
Latest version: 0.0.17

# @studiohyperdrive/swagger-express-ts

Register API endpoints and operations using TypeScript Decorators and generate Swagger Documentation automatically for your express application.

## Table of contents

* [Getting Started](#getting-started)
* [Usage](#usage)

## Getting Started

### Install the package

```bash
# NPM
npm install --save @studiohyperdrive/swagger-express-ts

# Yarn
yarn add --save @studiohyperdrive/swagger-express-ts
```

## Usage

See the `demo` folder for a working example.

### 1. Create a router for your api:

```typescript
import {
	ApiPath,
	Router,
} from '@studiohyperdrive/swagger-express-ts';

@ApiPath({
	path: '/demo',
	version: 1,
	description: 'Demo api',
})
class DemoV1Router extends Router {}
```

### 2. Add some definitions:

```typescript
import {
	ApiDefinition,
	SwaggerApiDefinitionProperties,
	SwaggerModelType,
} from '@studiohyperdrive/swagger-express-ts';

...
class DemoV1Router {
  @ApiDefinition({
		type: SwaggerModelType.OBJECT,
		description: 'Thing',
	})
	public static Thing: SwaggerApiDefinitionProperties = {
		count: {
			type: SwaggerModelType.NUMBER,
			description: 'count',
			required: true,
			example: 10,
		},
	};

	@ApiDefinition({
		type: SwaggerModelType.OBJECT,
		description: 'Item',
	})
	public static Item: SwaggerApiDefinitionProperties = {
		foo: {
			type: SwaggerModelType.STRING,
			description: 'bar',
			required: true,
			example: 'stuff and things',
		},
		thing: {
			type: SwaggerModelType.OBJECT,
			model: 'Thing',
			example: {},
		},
	};
}
```

### 3. Register an operation:

```typescript
import {
	ApiOperationGet,
	SwaggerResponseType,
	SwaggerUtils,
} from '@studiohyperdrive/swagger-express-ts';

...
class DemoV1Router {
	@ApiOperationGet({
		description: 'Get all items',
		responses: {
			200: {
				description: 'OK',
				type: SwaggerResponseType.ARRAY,
				model: 'Item'
			},
		},
	})
	public getItems(app: Application): void {
		app.route(this.baseUrl).get(
			SwaggerUtils.createController((req, res, next) => {
				return {
					total: 1,
					pages: 1,
					page: 1,
					size: 20,
					items: [{
						foo: 'bar',
						thing: {
						  count: 2,
						},
					}],
				};
			})
		);
	}
}
```

### 4. Use the middleware to serve your docs

```typescript
import express from 'express';
import { swaggerExpress } from '@studiohyperdrive/swagger-express-ts';

const app = express();

app.use(swaggerExpress({
	docsPath: '/docs',
	basePath: '/',
	info: {
		version: '1.0.0',
		title: 'My custom API',
	},
	host: 'localhost:3000',
	uiOptions: {
		customFavIcon: 'https://link.to.my/favicon.ico',
	},
}));
```

The docs will be available on the url you configured. For the example above that would be:

```bash
# [host]/[docsPath]

http://localhost:3000/docs
```

You can filter endpoints by API version:

```bash
# [host]/[docsPath]/[version]

http://localhost:3000/docs/v1
```

Or view the swagger spec as a json file:

```bash
# [host]/[docsPath]/json

http://localhost:3000/docs/json
```

## Decorators

There are 7 decorators you can use:

* `@ApiDefinition`: register a Swagger schema
* `@ApiPath`: register a new API base path
* `@ApiOperationGet`: register a GET operation
* `@ApiOperationPost`: register a POST operation
* `@ApiOperationPut`: register a PUT operation
* `@ApiOperationPatch`: register a PATCH operation
* `@ApiOperationDelete`: register a DELETE operation

## Utils

### createController

The `createController` util has 2 main functions:

1. Wrap your controller in a try/catch block and properly handle errors.
2. Remove the boilerplate of returning data.

```typescript
import { Request, Response, Next, SwaggerUtils } from '@studiohyperdrive/swagger-express-ts';

const controller = async (req: Request, res: Response, next: Next): Promise<Items> => {
	return await fetchThings(req.params);
};

SwaggerUtils.createController(controller);
```

Any value you return will be send back to the client as a JSON response with status 200.
Errors will be handled by the global error handling.

### extractVersion

The `extractVersion` util can be used to extract the version (number) from a number or string input:

```typescript
import { SwaggerUtils } from '@studiohyperdrive';

SwaggerUtils.extractVersion(1); // = 1
SwaggerUtils.extractVersion('1'); // = 1
SwaggerUtils.extractVersion('v1'); // = 1
SwaggerUtils.extractVersion(); // = null
SwaggerUtils.extractVersion('test'); // = null
```

### getBaseUrl

The `getBaseUrl` util can be used to get a base url from a path and/or version input:

```typescript
import { SwaggerUtils } from '@studiohyperdrive';

SwaggerUtils.getBaseUrl({ version: 1, path: '/demo' }); // = /v1/demo
SwaggerUtils.getBaseUrl({ path: '/demo' }); // = /demo
SwaggerUtils.getBaseUrl({ version: 'test', path: '/demo' }); // = /demo
```

### paginated

The `paginated` util can be used to get a paginated Swagger response:

```typescript
import { SwaggerUtils } from '@studiohyperdrive';

SwaggerUtils.paginated('Item', 'Item description');
```

```typescript
{
	description: 'Paginated result',
	type: 'object',
	properties: {
		items: {
			model: 'Item',
			description: 'Item description',
			type: 'array',
		},
		total: {
			type: 'number,
			required: true,
			example: 76,
		},
		pages: {
			type: 'number,
			required: true,
			example: 4,
		},
		page: {
			type: 'number,
			required: true,
			example: 1,
		},
		size: {
			type: 'number,
			required: true,
			example: 20,
		},
	}
}
```