Skip to content

Commit

Permalink
feat: Support passing in a REST endpoint method as first argument (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
gr2m committed Apr 15, 2020
1 parent e3f74ad commit 51e917d
Show file tree
Hide file tree
Showing 7 changed files with 460 additions and 23 deletions.
33 changes: 31 additions & 2 deletions README.md
Expand Up @@ -52,7 +52,7 @@ const issues = await octokit.paginate("GET /repos/:owner/:repo/issues", {
});
```

## `octokit.paginate(route, parameters, mapFunction)` or `octokit.paginate(options, mapFunction)`
## `octokit.paginate()`

The `paginateRest` plugin adds a new `octokit.paginate()` method which accepts the same parameters as [`octokit.request`](https://github.com/octokit/request.js#request). Only "List ..." endpoints such as [List issues for a repository](https://developer.github.com/v3/issues/#list-issues-for-a-repository) are supporting pagination. Their [response includes a Link header](https://developer.github.com/v3/issues/#response-1). For other endpoints, `octokit.paginate()` behaves the same as `octokit.request()`.

Expand Down Expand Up @@ -93,7 +93,18 @@ const issues = await octokit.paginate(
);
```

## `octokit.paginate.iterator(route, parameters)` or `octokit.paginate.iterator(options)`
Alternatively you can pass a `request` method as first argument. This is great when using in combination with [`@octokit/plugin-rest-endpoint-methods`](https://github.com/octokit/plugin-rest-endpoint-methods.js/):

```js
const issues = await octokit.paginate(octokit.issues.listForRepo, {
owner: "octocat",
repo: "hello-world",
since: "2010-10-01",
per_page: 100,
});
```

## `octokit.paginate.iterator()`

If your target runtime environments supports async iterators (such as most modern browsers and Node 10+), you can iterate through each response

Expand All @@ -113,6 +124,24 @@ for await (const response of octokit.paginate.iterator(
}
```

Alternatively you can pass a `request` method as first argument. This is great when using in combination with [`@octokit/plugin-rest-endpoint-methods`](https://github.com/octokit/plugin-rest-endpoint-methods.js/):

```js
const parameters = {
owner: "octocat",
repo: "hello-world",
since: "2010-10-01",
per_page: 100,
};
for await (const response of octokit.paginate.iterator(
octokit.issues.listForRepo,
parameters
)) {
// do whatever you want with each response, break out of the loop, etc.
console.log(response.data.title);
}
```

## How it works

`octokit.paginate()` wraps `octokit.request()`. As long as a `rel="next"` link value is present in the response's `Link` header, it sends another request for that URL, and so on.
Expand Down
94 changes: 91 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -21,7 +21,7 @@
],
"license": "MIT",
"dependencies": {
"@octokit/types": "^2.0.1"
"@octokit/types": "^2.9.0"
},
"devDependencies": {
"@octokit/core": "^2.0.0",
Expand Down
20 changes: 14 additions & 6 deletions src/iterator.ts
@@ -1,14 +1,24 @@
import { Octokit } from "@octokit/core";

import { normalizePaginatedListResponse } from "./normalize-paginated-list-response";
import { OctokitResponse, RequestParameters, Route } from "./types";
import {
EndpointOptions,
RequestInterface,
OctokitResponse,
RequestParameters,
Route,
} from "./types";

export function iterator(
octokit: Octokit,
route: Route,
route: Route | RequestInterface,
parameters?: RequestParameters
) {
const options = octokit.request.endpoint(route, parameters);
const options =
typeof route === "function"
? route.endpoint(parameters as EndpointOptions)
: octokit.request.endpoint(route, parameters);
const requestMethod = typeof route === "function" ? route : octokit.request;
const method = options.method;
const headers = options.headers;
let url = options.url;
Expand All @@ -20,9 +30,7 @@ export function iterator(
return Promise.resolve({ done: true });
}

return octokit
.request({ method, url, headers })

return requestMethod({ method, url, headers })
.then(normalizePaginatedListResponse)

.then((response: OctokitResponse<any>) => {
Expand Down
3 changes: 2 additions & 1 deletion src/paginate.ts
Expand Up @@ -6,11 +6,12 @@ import {
PaginationResults,
RequestParameters,
Route,
RequestInterface,
} from "./types";

export function paginate(
octokit: Octokit,
route: Route,
route: Route | RequestInterface,
parameters?: RequestParameters,
mapFn?: MapFunction
) {
Expand Down
56 changes: 52 additions & 4 deletions src/types.ts
@@ -1,9 +1,12 @@
import * as OctokitTypes from "@octokit/types";

export { EndpointOptions } from "@octokit/types";
export { OctokitResponse } from "@octokit/types";
export { RequestParameters } from "@octokit/types";
export { Route } from "@octokit/types";
export {
EndpointOptions,
RequestInterface,
OctokitResponse,
RequestParameters,
Route,
} from "@octokit/types";

export interface PaginateInterface {
/**
Expand Down Expand Up @@ -65,6 +68,37 @@ export interface PaginateInterface {
*/
<T>(route: OctokitTypes.Route): Promise<PaginationResults<T>>;

/**
* Paginate a request using an endpoint route string and parameters
*
* @param {string} request Request method (`octokit.request` or `@octokit/request`)
* @param {object} parameters URL, query or body parameters, as well as `headers`, `mediaType.{format|previews}`, `request`, or `baseUrl`.
* @param {function} mapFn Optional method to map each response to a custom array
*/
<T, R>(
request: OctokitTypes.RequestInterface,
parameters: OctokitTypes.RequestParameters,
mapFn: MapFunction<T>
): Promise<PaginationResults<R>>;

/**
* Paginate a request using an endpoint route string and parameters
*
* @param {string} request Request method (`octokit.request` or `@octokit/request`)
* @param {object} parameters URL, query or body parameters, as well as `headers`, `mediaType.{format|previews}`, `request`, or `baseUrl`.
*/
<T>(
request: OctokitTypes.RequestInterface,
parameters: OctokitTypes.RequestParameters
): Promise<PaginationResults<T>>;

/**
* Paginate a request using an endpoint function
*
* @param {function} request `octokit.endpoint` or `@octokit/endpoint` compatible method
*/
<T>(request: OctokitTypes.RequestInterface): Promise<PaginationResults<T>>;

iterator: {
/**
* Get an async iterator to paginate a request using endpoint options
Expand All @@ -89,6 +123,20 @@ export interface PaginateInterface {
): AsyncIterableIterator<
OctokitTypes.OctokitResponse<PaginationResults<T>>
>;

/**
* Get an async iterator to paginate a request using a request method and optional parameters
*
* @see {link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of} for await...of
* @param {string} request `@octokit/request` or `octokit.request` method
* @param {object} [parameters] URL, query or body parameters, as well as `headers`, `mediaType.{format|previews}`, `request`, or `baseUrl`.
*/
<T>(
request: OctokitTypes.RequestInterface,
parameters?: OctokitTypes.RequestParameters
): AsyncIterableIterator<
OctokitTypes.OctokitResponse<PaginationResults<T>>
>;
};
}

Expand Down

0 comments on commit 51e917d

Please sign in to comment.