Skip to content

Commit

Permalink
feat: Add API docs
Browse files Browse the repository at this point in the history
  • Loading branch information
berstend committed Nov 29, 2019
1 parent 5e7d69b commit f7b2676
Show file tree
Hide file tree
Showing 4 changed files with 2,765 additions and 47 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"build": "rollup -c rollup.config.ts && npm run declarations",
"dev": "npm run prebuild && rollup -c rollup.config.ts -w && npm run declarations",
"test": "ava-ts -v",
"prepublish": "npm run build"
"prepublish": "npm run build",
"docs": "documentation readme --quiet --shallow --github --markdown-theme transitivebs --readme-file readme.md --section API ./src/router.ts && npx prettier --write readme.md && npx prettier --write readme.md"
},
"prettier": {
"printWidth": 100,
Expand All @@ -50,6 +51,7 @@
"@types/node": "^12.12.14",
"ava": "^2.4.0",
"ava-ts": "^0.25.1",
"documentation-markdown-themes": "^12.1.5",
"rimraf": "^3.0.0",
"rollup": "^1.27.5",
"rollup-plugin-commonjs": "^10.1.0",
Expand Down
218 changes: 217 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,225 @@ addEventListener('fetch', event => {
})
```

---

## API

The API is extremely minimal and what you would expect (`.get()`, `.all()`, etc). Please check out the [tiny source code](src/router.ts) or [tests](test/functionality.ts) for more info.
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

#### Table of Contents

- [Method()](#method)
- [RouteOptions()](#routeoptions)
- [RouteMatch()](#routematch)
- [class: Router](#class-router)
- [.routes](#routes)
- [.all(path, handler, options)](#allpath-handler-options)
- [.get(path, handler, options)](#getpath-handler-options)
- [.post(path, handler, options)](#postpath-handler-options)
- [.put(path, handler, options)](#putpath-handler-options)
- [.patch(path, handler, options)](#patchpath-handler-options)
- [.delete(path, handler, options)](#deletepath-handler-options)
- [.head(path, handler, options)](#headpath-handler-options)
- [.options(path, handler, options)](#optionspath-handler-options)
- [.match(method, path)](#matchmethod-path)

### [Method()](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L6-L6)

Type: **(`"GET"` \| `"POST"` \| `"PUT"` \| `"PATCH"` \| `"DELETE"` \| `"HEAD"` \| `"OPTIONS"`)**

Valid HTTP methods for matching.

---

### [RouteOptions()](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L39-L39)

**Extends: TokensToRegexpOptions**

Optional route options.

Example:

```javascript
// When `true` the regexp will be case sensitive. (default: `false`)
sensitive?: boolean;

// When `true` the regexp allows an optional trailing delimiter to match. (default: `false`)
strict?: boolean;

// When `true` the regexp will match to the end of the string. (default: `true`)
end?: boolean;

// When `true` the regexp will match from the beginning of the string. (default: `true`)
start?: boolean;

// Sets the final character for non-ending optimistic matches. (default: `/`)
delimiter?: string;

// List of characters that can also be "end" characters.
endsWith?: string;

// Encode path tokens for use in the `RegExp`.
encode?: (value: string) => string;
```

---

### [RouteMatch()](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L67-L70)

**Extends: Route&lt;HandlerType>**

The object returned when a route matches.

The handler can then be used to execute the relevant function.

Example:

```javascript
{
params: Params
matches?: RegExpExecArray
method: Method | MethodWildcard
path: string
regexp: RegExp
options: RouteOptions
keys: Keys
handler: HandlerType
}
```

---

### class: [Router](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L86-L168)

Tiny request router. Allows overloading of handler type to be fully type safe.

Example:

```javascript
import { Router, Method, Params } from 'tiny-request-router'

// Let the router know that handlers are async functions returning a Response
type Handler = (params: Params) => Promise<Response>

const router = new Router<Handler>()
```

---

#### .[routes](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L88-L88)

List of all registered routes.

---

#### .[all(path, handler, options)](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L91-L93)

- `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `handler` **HandlerType**
- `options` **[RouteOptions](#routeoptions)** (optional, default `{}`)

Add a route that matches any method.

---

#### .[get(path, handler, options)](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L95-L97)

- `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `handler` **HandlerType**
- `options` **[RouteOptions](#routeoptions)** (optional, default `{}`)

Add a route that matches the GET method.

---

#### .[post(path, handler, options)](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L99-L101)

- `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `handler` **HandlerType**
- `options` **[RouteOptions](#routeoptions)** (optional, default `{}`)

Add a route that matches the POST method.

---

#### .[put(path, handler, options)](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L103-L105)

- `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `handler` **HandlerType**
- `options` **[RouteOptions](#routeoptions)** (optional, default `{}`)

Add a route that matches the PUT method.

---

#### .[patch(path, handler, options)](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L107-L109)

- `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `handler` **HandlerType**
- `options` **[RouteOptions](#routeoptions)** (optional, default `{}`)

Add a route that matches the PATCH method.

---

#### .[delete(path, handler, options)](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L111-L113)

- `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `handler` **HandlerType**
- `options` **[RouteOptions](#routeoptions)** (optional, default `{}`)

Add a route that matches the DELETE method.

---

#### .[head(path, handler, options)](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L115-L117)

- `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `handler` **HandlerType**
- `options` **[RouteOptions](#routeoptions)** (optional, default `{}`)

Add a route that matches the HEAD method.

---

#### .[options(path, handler, options)](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L119-L121)

- `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `handler` **HandlerType**
- `options` **[RouteOptions](#routeoptions)** (optional, default `{}`)

Add a route that matches the OPTIONS method.

---

#### .[match(method, path)](https://github.com/berstend/tiny-request-router/blob/5e7d69be1e37a6d2d14c611efe77ba2ef6ea9f83/src/router.ts#L135-L152)

- `method` **[Method](#method)**
- `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**

Returns: **([RouteMatch](#routematch)&lt;HandlerType> | null)**

Match the provided method and path against the list of registered routes.

Example:

```javascript
router.get('/foobar', async () => new Response('Hello'))

const match = router.match('GET', '/foobar')
if (match) {
// Call the async function of that match
const response = await match.handler()
console.log(response) // => Response('Hello')
}
```

---

## More info

Please check out the [tiny source code](src/router.ts) or [tests](test/functionality.ts) for more info.

## License

Expand Down
95 changes: 85 additions & 10 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,41 @@ import { Key as TokenKey, pathToRegexp, TokensToRegexpOptions } from 'path-to-re
// https://basarat.gitbooks.io/typescript/docs/tips/barrel.html
export { pathToRegexp }

/** Valid HTTP methods for matching. */
export type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'
export type MethodWildcard = 'ALL'

export interface Params {
[key: string]: string
}

/**
* Optional route options.
*
* @example
* // When `true` the regexp will be case sensitive. (default: `false`)
* sensitive?: boolean;
*
* // When `true` the regexp allows an optional trailing delimiter to match. (default: `false`)
* strict?: boolean;
*
* // When `true` the regexp will match to the end of the string. (default: `true`)
* end?: boolean;
*
* // When `true` the regexp will match from the beginning of the string. (default: `true`)
* start?: boolean;
*
* // Sets the final character for non-ending optimistic matches. (default: `/`)
* delimiter?: string;
*
* // List of characters that can also be "end" characters.
* endsWith?: string;
*
* // Encode path tokens for use in the `RegExp`.
* encode?: (value: string) => string;
*/
export interface RouteOptions extends TokensToRegexpOptions {}

export interface Route<HandlerType> {
method: Method | MethodWildcard
path: string
Expand All @@ -12,51 +47,91 @@ export interface Route<HandlerType> {
handler: HandlerType
}

/**
* The object returned when a route matches.
*
* The handler can then be used to execute the relevant function.
*
* @example
* {
* params: Params
* matches?: RegExpExecArray
* method: Method | MethodWildcard
* path: string
* regexp: RegExp
* options: RouteOptions
* keys: Keys
* handler: HandlerType
* }
*/
export interface RouteMatch<HandlerType> extends Route<HandlerType> {
params: Params
matches?: RegExpExecArray
}

export type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'
export type MethodWildcard = 'ALL'

export interface Params {
[key: string]: string
}

export interface RouteOptions extends TokensToRegexpOptions {}

export type Key = TokenKey
export type Keys = Array<Key>

/**
* Tiny request router. Allows overloading of handler type to be fully type safe.
*
* @example
* import { Router, Method, Params } from 'tiny-request-router'
*
* // Let the router know that handlers are async functions returning a Response
* type Handler = (params: Params) => Promise<Response>
*
* const router = new Router<Handler>()
*/
export class Router<HandlerType = any> {
/** List of all registered routes. */
public routes: Array<Route<HandlerType>> = []

/** Add a route that matches any method. */
public all(path: string, handler: HandlerType, options: RouteOptions = {}) {
return this._push('ALL', path, handler, options)
}
/** Add a route that matches the GET method. */
public get(path: string, handler: HandlerType, options: RouteOptions = {}) {
return this._push('GET', path, handler, options)
}
/** Add a route that matches the POST method. */
public post(path: string, handler: HandlerType, options: RouteOptions = {}) {
return this._push('POST', path, handler, options)
}
/** Add a route that matches the PUT method. */
public put(path: string, handler: HandlerType, options: RouteOptions = {}) {
return this._push('PUT', path, handler, options)
}
/** Add a route that matches the PATCH method. */
public patch(path: string, handler: HandlerType, options: RouteOptions = {}) {
return this._push('PATCH', path, handler, options)
}
/** Add a route that matches the DELETE method. */
public delete(path: string, handler: HandlerType, options: RouteOptions = {}) {
return this._push('DELETE', path, handler, options)
}
/** Add a route that matches the HEAD method. */
public head(path: string, handler: HandlerType, options: RouteOptions = {}) {
return this._push('HEAD', path, handler, options)
}
/** Add a route that matches the OPTIONS method. */
public options(path: string, handler: HandlerType, options: RouteOptions = {}) {
return this._push('OPTIONS', path, handler, options)
}

/**
* Match the provided method and path against the list of registered routes.
*
* @example
* router.get('/foobar', async () => new Response('Hello'))
*
* const match = router.match('GET', '/foobar')
* if (match) {
* // Call the async function of that match
* const response = await match.handler()
* console.log(response) // => Response('Hello')
* }
*/
public match(method: Method, path: string): RouteMatch<HandlerType> | null {
for (const route of this.routes) {
// Skip immediately if method doesn't match
Expand Down
Loading

0 comments on commit f7b2676

Please sign in to comment.