-
Notifications
You must be signed in to change notification settings - Fork 227
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(domains): update custom domains functionality (#2920)
* WIP add custom domain length check logic * Add @inquirer/prompts * WIP add prompt and logic to domains * WIP add paginator * WIP add paginator part 2 * WIP add paginator part 3 * WIP add paginator part 4 * WIP working request for next-range headers * WIP update draft copy and mute logs * Add total number of domains in prompt * WIP add total number of domains in prompt for filtered domains Need to update types and update logic for when this condition will be true. Currently defaulted to true verify size of filtered domains * WIP create interface & update logic * WIP update logic * WIP update logic part 2 * WIP update logic part 3 * Update pagninator and domains request * Update ux.log() and comments * Update prompt * Refactor keyValueParser into utility * Update paginator arguments & comments * Clean up paginator * Code clean up * Add tests * Add tests part 2 * Update copy from CX review * WIP last test debug * Add last test * Update yarn.lock * Update test * Add generics for any types
- Loading branch information
1 parent
f5027db
commit 045eab4
Showing
8 changed files
with
395 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export default function parseKeyValue(input: string) { | ||
let [key, value] = input.split(/=(.+)/) | ||
|
||
key = key.trim() | ||
value = value ? value.trim() : '' | ||
|
||
return {key, value} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// page size ranges from 200 - 1000 seen here | ||
// https://devcenter.heroku.com/articles/platform-api-reference#ranges | ||
|
||
// This paginator uses status code to determine passing the Next-Range header | ||
import {APIClient} from '@heroku-cli/command' | ||
import HTTP from 'http-call' | ||
|
||
export async function paginateRequest<T = unknown>(client: APIClient, url: string, pageSize = 200): Promise<T[]> { | ||
let isPartial = true | ||
let isFirstRequest = true | ||
let nextRange: string | undefined = '' | ||
let aggregatedResponseBody: T[] = [] | ||
|
||
while (isPartial) { | ||
const response: HTTP<T[]> = await client.get<T[]>(url, { | ||
headers: { | ||
Range: `${(isPartial && !isFirstRequest) ? `${nextRange}` : `id ..; max=${pageSize};`}`, | ||
}, | ||
partial: true, | ||
}) | ||
|
||
aggregatedResponseBody = [...response.body, ...aggregatedResponseBody] | ||
isFirstRequest = false | ||
|
||
if (response.statusCode === 206) { | ||
nextRange = response.headers['next-range'] as string | ||
} else { | ||
isPartial = false | ||
} | ||
} | ||
|
||
return aggregatedResponseBody | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import {expect} from '@oclif/test' | ||
import parseKeyValue from '../../../src/lib/utils/keyValueParser' | ||
|
||
const exampleInput1 = 'Domain Name=ztestdomain7' | ||
const exampleInput2 = 'exampleKey=value' | ||
const exampleInput3 = 'example key=example value' | ||
|
||
describe('keyValueParser', () => { | ||
it('parses and extracts key/value pairs', () => { | ||
const {key: exampleKey1, value: exampleValue1} = parseKeyValue(exampleInput1) | ||
const {key: exampleKey2, value: exampleValue2} = parseKeyValue(exampleInput2) | ||
const {key: exampleKey3, value: exampleValue3} = parseKeyValue(exampleInput3) | ||
|
||
expect(exampleKey1).to.equal('Domain Name') | ||
expect(exampleValue1).to.equal('ztestdomain7') | ||
expect(exampleKey2).to.equal('exampleKey') | ||
expect(exampleValue2).to.equal('value') | ||
expect(exampleKey3).to.equal('example key') | ||
expect(exampleValue3).to.equal('example value') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import {expect} from '@oclif/test' | ||
import {Config} from '@oclif/core' | ||
import {paginateRequest} from '../../../src/lib/utils/paginator' | ||
import {APIClient} from '@heroku-cli/command' | ||
import * as Heroku from '@heroku-cli/schema' | ||
import * as nock from 'nock' | ||
|
||
const path = require('path') | ||
const root = path.resolve(__dirname, '../package.json') | ||
const config = new Config({root}) | ||
const exampleAPIClient = new APIClient(config) | ||
|
||
nock.disableNetConnect() | ||
|
||
const requestUrl = '/apps/myapp/domains' | ||
|
||
describe('paginator', function () { | ||
it('paginates through 2 requests', async function () { | ||
nock('https://api.heroku.com') | ||
.get(requestUrl) | ||
.reply(206, [{id: '1'}], {'next-range': 'id ..; max=200'}) | ||
.get(requestUrl) | ||
.reply(200, [{id: '2'}]) | ||
|
||
const results = await paginateRequest<Heroku.Domain>(exampleAPIClient, requestUrl, 200) | ||
expect(results).to.have.length(2) | ||
expect(results[0].id).to.equal('2') | ||
expect(results[1].id).to.equal('1') | ||
}) | ||
|
||
it('serves single requests', async function () { | ||
nock('https://api.heroku.com') | ||
.get(requestUrl) | ||
.reply(200, [{id: '1'}]) | ||
|
||
const results = await paginateRequest<Heroku.Domain>(exampleAPIClient, requestUrl, 200) | ||
expect(results).to.have.length(1) | ||
expect(results).to.not.have.length(2) | ||
expect(results[0].id).to.equal('1') | ||
}) | ||
}) |
Oops, something went wrong.