Skip to content

Commit

Permalink
feat: composePaginateRest (#207)
Browse files Browse the repository at this point in the history
  • Loading branch information
gr2m authored Oct 31, 2020
1 parent d68294e commit e5c7e6f
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 21 deletions.
4 changes: 4 additions & 0 deletions src/compose-paginate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { paginate } from "./paginate";
import { iterator } from "./iterator";

export const composePaginateRest = Object.assign(paginate, { iterator });
7 changes: 4 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { VERSION } from "./version";
import { Octokit } from "@octokit/core";

import { VERSION } from "./version";
import { paginate } from "./paginate";
import { iterator } from "./iterator";
import { PaginateInterface } from "./types";
export { PaginateInterface } from "./types";

import { Octokit } from "@octokit/core";
export { PaginateInterface } from "./types";
export { composePaginateRest } from "./compose-paginate";

/**
* @param octokit Octokit instance
Expand Down
27 changes: 11 additions & 16 deletions src/iterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { normalizePaginatedListResponse } from "./normalize-paginated-list-respo
import {
EndpointOptions,
RequestInterface,
OctokitResponse,
RequestParameters,
Route,
} from "./types";
Expand All @@ -25,24 +24,20 @@ export function iterator(

return {
[Symbol.asyncIterator]: () => ({
next() {
if (!url) {
return Promise.resolve({ done: true });
}
async next() {
if (!url) return { done: true };

return requestMethod({ method, url, headers })
.then(normalizePaginatedListResponse)
const response = await requestMethod({ method, url, headers });
const normalizedResponse = normalizePaginatedListResponse(response);

.then((response: OctokitResponse<any>) => {
// `response.headers.link` format:
// '<https://api.github.com/users/aseemk/followers?page=2>; rel="next", <https://api.github.com/users/aseemk/followers?page=2>; rel="last"'
// sets `url` to undefined if "next" URL is not present or `link` header is not set
url = ((response.headers.link || "").match(
/<([^>]+)>;\s*rel="next"/
) || [])[1];
// `response.headers.link` format:
// '<https://api.github.com/users/aseemk/followers?page=2>; rel="next", <https://api.github.com/users/aseemk/followers?page=2>; rel="last"'
// sets `url` to undefined if "next" URL is not present or `link` header is not set
url = ((normalizedResponse.headers.link || "").match(
/<([^>]+)>;\s*rel="next"/
) || [])[1];

return { value: response };
});
return { value: normalizedResponse };
},
}),
};
Expand Down
78 changes: 78 additions & 0 deletions test/compose-paginate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import fetchMock from "fetch-mock";
import { Octokit } from "@octokit/core";
import { restEndpointMethods } from "@octokit/plugin-rest-endpoint-methods";

import { composePaginateRest } from "../src";

const ORG1 = { id: 1 };
const ORG2 = { id: 2 };

test("composePaginateRest(octokit, route)", async () => {
const mock = fetchMock
.sandbox()
.get("https://api.github.com/orgs/octokit/repos?per_page=1", {
body: [ORG1],
headers: {
link:
'<https://pagination-test.com/orgs/octokit/repos?page=2&per_page=1>; rel="next"',
"X-GitHub-Media-Type": "github.v3; format=json",
},
})
.get("https://pagination-test.com/orgs/octokit/repos?page=2&per_page=1", {
body: [ORG2],
headers: {},
});

const octokit = new Octokit({
request: {
fetch: mock,
},
});

const organizations = await composePaginateRest(
octokit,
"GET /orgs/:org/repos",
{
org: "octokit",
per_page: 1,
}
);
expect(organizations).toStrictEqual([ORG1, ORG2]);
});

test("composePaginateRest.iterator(octokit, route)", () => {
const mock = fetchMock
.sandbox()
.getOnce("https://api.github.com/organizations", {
body: [ORG1],
headers: {
link: '<https://pagination-test.com/organizations?since=2>; rel="next"',
"X-GitHub-Media-Type": "github.v3; format=json",
},
})
.getOnce("https://pagination-test.com/organizations?since=2", {
body: [ORG2],
headers: {},
});

const octokit = new Octokit({
request: {
fetch: mock,
},
});

const iterator = composePaginateRest
.iterator(octokit, "GET /organizations")
[Symbol.asyncIterator]();

return iterator
.next()
.then((result: any) => {
expect(result.value.data[0].id).toEqual(1);

return iterator.next();
})
.then((result: any) => {
expect(result.value.data[0].id).toEqual(2);
});
});
8 changes: 6 additions & 2 deletions test/smoke.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { Octokit } from "@octokit/core";

import { paginateRest } from "../src";
import { paginateRest, composePaginateRest } from "../src";

describe("Smoke test", () => {
it("is a function", () => {
it("paginateRest", () => {
expect(paginateRest).toBeInstanceOf(Function);
});

it("paginateRest.VERSION is set", () => {
expect(paginateRest.VERSION).toEqual("0.0.0-development");
});

it("composePaginateRest", () => {
expect(composePaginateRest).toBeInstanceOf(Function);
});

it("Loads plugin", () => {
const TestOctokit = Octokit.plugin(paginateRest);
const testOctokit = new TestOctokit();
Expand Down

0 comments on commit e5c7e6f

Please sign in to comment.