Skip to content

Commit f69136e

Browse files
committed
Add pagination support
1 parent cfb9bee commit f69136e

File tree

4 files changed

+71
-44
lines changed

4 files changed

+71
-44
lines changed

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
"@types/chai": "^4.1.4",
2424
"@types/mocha": "^5.2.5",
2525
"@types/nock": "^9.3.0",
26-
"@types/node": "^10.7.1",
26+
"@types/node": "^20.14.8",
2727
"@types/node-fetch": "^2.1.2",
2828
"mocha": "^5",
2929
"nock": "^9.2.6",
3030
"nyc": "^11",
3131
"ts-node": "^6",
3232
"tslint": "^5.11.0",
33-
"typescript": "^2.8"
33+
"typescript": "^5.7"
3434
},
3535
"dependencies": {
3636
"node-fetch": "^2.2.0",
@@ -41,5 +41,6 @@
4141
},
4242
"files": [
4343
"/dist"
44-
]
44+
],
45+
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
4546
}

src/buildpack-registry-api.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import fetch, {Headers, RequestInit, Response} from 'node-fetch'
1+
import fetch, { Headers, RequestInit, Response } from 'node-fetch'
22

3-
export {Response} from 'node-fetch'
3+
export { Response } from 'node-fetch'
44

55
export type IBody = {
66
[property: string]: string
@@ -85,7 +85,7 @@ export class BuildpackRegistryApi {
8585
}
8686

8787
headers(options: HeaderOptions = {}): Headers {
88-
let defaultHeaders: {[property: string]: string} = {
88+
let defaultHeaders: { [property: string]: string } = {
8989
Accept: 'application/vnd.heroku+json; version=3.buildpack-registry',
9090
'Content-Type': 'application/json'
9191
}
@@ -99,7 +99,7 @@ export class BuildpackRegistryApi {
9999

100100
if (process.env.HEROKU_HEADERS) {
101101
let herokuHeaders = JSON.parse(process.env.HEROKU_HEADERS)
102-
return new Headers({...defaultHeaders, herokuHeaders})
102+
return new Headers({ ...defaultHeaders, herokuHeaders })
103103
} else {
104104
return new Headers(defaultHeaders)
105105
}
@@ -117,9 +117,9 @@ export class BuildpackRegistryApi {
117117
return fetch(`${BuildpackRegistryApi.url()}${path}`, options)
118118
}
119119

120-
async get(path: string): Promise<Response> {
121-
return fetch(`${BuildpackRegistryApi.url()}${path}`, {
122-
headers: this.headers()
123-
})
120+
async get(path: string, headers?: Headers): Promise<Response> {
121+
return await fetch(`${BuildpackRegistryApi.url()}${path}`, {
122+
headers: headers ? headers : this.headers(),
123+
});
124124
}
125125
}

src/buildpack-registry.ts

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import {Result} from 'true-myth'
1+
import { Result } from 'true-myth'
22

3-
import {BuildpackBody, BuildpackRegistryApi as Api, Category, HeaderOptions, ReadmeBody, Response, RevisionBody, RevisionStatus} from './buildpack-registry-api'
3+
import { BuildpackBody, BuildpackRegistryApi as Api, Category, HeaderOptions, ReadmeBody, Response, RevisionBody, RevisionStatus } from './buildpack-registry-api'
44

5-
export {BuildpackBody, Category, ReadmeBody, RevisionBody, RevisionStatus}
5+
import { Headers } from 'node-fetch'
6+
7+
export { BuildpackBody, Category, ReadmeBody, RevisionBody, RevisionStatus }
68

79
const BUILDPACK_FORMATTING_MESSAGE = "To specify a buildpack, please format it like the following: namespace/name (e.g. heroku/ruby). Also names can only contain letters, numbers, '_', and '-'."
810

@@ -58,15 +60,41 @@ export class BuildpackRegistry {
5860
}
5961
}
6062

63+
async list(path: string): Promise<Result<Array<any>, ResponseError>> {
64+
let page = await this.api.get(path);
65+
let items = [];
66+
if (page.status === 200 || page.status === 206) {
67+
items = await page.json();
68+
}
69+
while (page.status === 206) {
70+
let nextRange = page.headers.get('Next-Range')
71+
if (typeof nextRange !== "string") {
72+
break;
73+
}
74+
page = await this.api.get(path, new Headers({ 'Accept-Range': nextRange}));
75+
if (page.status === 200 || page.status === 206) {
76+
items = [...items, ...await page.json()];
77+
}
78+
}
79+
if (page.status !== 200) {
80+
return Result.err({
81+
status: page.status,
82+
path,
83+
description: await page.text()
84+
});
85+
}
86+
return Result.ok(items);
87+
}
88+
6189
async publish(buildpack: string, ref: string, token: string, secondFactor?: string): Promise<Result<RevisionBody, ResponseError>> {
62-
let options: HeaderOptions = {token}
90+
let options: HeaderOptions = { token }
6391
if (secondFactor !== undefined) {
6492
options.secondFactor = secondFactor
6593
}
6694
let path = `/buildpacks/${encodeURIComponent(buildpack)}/revisions`
6795
let response = await this.api.post(
6896
path,
69-
{ref},
97+
{ ref },
7098
this.api.headers(options))
7199

72100
if (response.status === 200) {
@@ -81,7 +109,7 @@ export class BuildpackRegistry {
81109
}
82110

83111
async rollback(buildpack: string, token: string, secondFactor?: string): Promise<Result<RevisionBody, ResponseError>> {
84-
let options: HeaderOptions = {token}
112+
let options: HeaderOptions = { token }
85113
if (secondFactor !== undefined) {
86114
options.secondFactor = secondFactor
87115
}
@@ -123,16 +151,7 @@ export class BuildpackRegistry {
123151
}
124152

125153
let path = `/buildpacks${queryString}`
126-
let response = await this.api.get(path)
127-
if (response.status === 200) {
128-
return Result.ok(await response.json())
129-
} else {
130-
return Result.err({
131-
status: response.status,
132-
path,
133-
description: await response.text(),
134-
})
135-
}
154+
return this.list(path);
136155
}
137156

138157
async info(buildpack: string): Promise<Result<InfoData, ResponseError>> {
@@ -189,14 +208,18 @@ export class BuildpackRegistry {
189208
}
190209

191210
if (readme.content) {
192-
data.readme = `\n${Buffer.from(readme.content, readme.encoding).toString()}`
211+
let encoding: BufferEncoding = 'utf8';
212+
if (readme.encoding && ['ascii', 'utf16le', 'latin1', 'base64', 'base64url'].includes(readme.encoding)) {
213+
encoding = readme.encoding as BufferEncoding;
214+
}
215+
data.readme = `\n${Buffer.from(readme.content, encoding).toString()}`
193216
}
194217

195218
return Result.ok(data)
196219
}
197220

198221
async archive(buildpack: string, token: string, secondFactor?: string): Promise<Result<BuildpackBody, ResponseError>> {
199-
let options: HeaderOptions = {token}
222+
let options: HeaderOptions = { token }
200223
if (secondFactor !== undefined) {
201224
options.secondFactor = secondFactor
202225
}
@@ -233,17 +256,7 @@ export class BuildpackRegistry {
233256

234257
async listVersions(buildpack: string): Promise<Result<RevisionBody[], ResponseError>> {
235258
let path = `/buildpacks/${encodeURIComponent(buildpack)}/revisions`
236-
let response = await this.api.get(path)
237-
238-
if (response.status === 200) {
239-
return Result.ok(await response.json())
240-
} else {
241-
return Result.err({
242-
status: response.status,
243-
path,
244-
description: await response.text()
245-
})
246-
}
259+
return await this.list(path)
247260
}
248261

249262
async delay(ms: number) {

yarn.lock

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,17 @@
2222
dependencies:
2323
"@types/node" "*"
2424

25-
"@types/node@*", "@types/node@^10.7.1":
25+
"@types/node@*":
2626
version "10.7.1"
2727
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.7.1.tgz#b704d7c259aa40ee052eec678758a68d07132a2e"
2828

29+
"@types/node@^20.14.8":
30+
version "20.17.16"
31+
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.16.tgz#b33b0edc1bf925b27349e494b871ca4451fabab4"
32+
integrity sha512-vOTpLduLkZXePLxHiHsBLp98mHGnl8RptV4YAO3HfKO5UHjDvySGbxKtpYfy8Sx5+WKcgc45qNreJJRVM3L6mw==
33+
dependencies:
34+
undici-types "~6.19.2"
35+
2936
ansi-regex@^2.0.0:
3037
version "2.1.1"
3138
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
@@ -1636,14 +1643,20 @@ type-detect@^4.0.0:
16361643
version "4.0.8"
16371644
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
16381645

1639-
typescript@^2.8:
1640-
version "2.9.2"
1641-
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
1646+
typescript@^5.7:
1647+
version "5.7.3"
1648+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e"
1649+
integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==
16421650

16431651
uglify-js@^3.1.4:
16441652
version "3.19.3"
16451653
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f"
16461654

1655+
undici-types@~6.19.2:
1656+
version "6.19.8"
1657+
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
1658+
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
1659+
16471660
union-value@^1.0.0:
16481661
version "1.0.0"
16491662
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"

0 commit comments

Comments
 (0)