Skip to content

feat: add region support #39

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions src/__tests__/client.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { createGotClient } from '../client';
import { DEFAULT_TEST_CLIENT_CONFIG } from '../__fixtures__/base-fixtures';

describe('createGotClient', () => {
test('works with default configuration', () => {
const config = DEFAULT_TEST_CLIENT_CONFIG;
const client = createGotClient(config);
const options = client.defaults.options;
expect(options.prefixUrl).toBe('https://serverless.twilio.com/v1/');
expect(options.responseType).toBe('json');
expect((options as any).username).toBe(
DEFAULT_TEST_CLIENT_CONFIG.accountSid
);
expect((options as any).password).toBe(
DEFAULT_TEST_CLIENT_CONFIG.authToken
);
expect(client.twilioClientConfig).toEqual(config);
});

test('works with region configuration', () => {
const config = {
...DEFAULT_TEST_CLIENT_CONFIG,
region: 'dev',
};
const client = createGotClient(config);
const options = client.defaults.options;
expect(options.prefixUrl).toBe('https://serverless.dev.twilio.com/v1/');
expect(options.responseType).toBe('json');
expect((options as any).username).toBe(
DEFAULT_TEST_CLIENT_CONFIG.accountSid
);
expect((options as any).password).toBe(
DEFAULT_TEST_CLIENT_CONFIG.authToken
);
expect(client.twilioClientConfig).toEqual(config);
});

test('works with region & edge configuration', () => {
const config = {
...DEFAULT_TEST_CLIENT_CONFIG,
edge: 'sydney',
region: 'au1',
};
const client = createGotClient(config);
const options = client.defaults.options;
expect(options.prefixUrl).toBe(
'https://serverless.sydney.au1.twilio.com/v1/'
);
expect(options.responseType).toBe('json');
expect((options as any).username).toBe(
DEFAULT_TEST_CLIENT_CONFIG.accountSid
);
expect((options as any).password).toBe(
DEFAULT_TEST_CLIENT_CONFIG.authToken
);
expect(client.twilioClientConfig).toEqual(config);
});
});
5 changes: 3 additions & 2 deletions src/api/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import {
VersionResource,
} from '../types';
import { getContentType } from '../utils/content-type';
import { getPaginatedResource } from './utils/pagination';
import { ClientApiError } from '../utils/error';
import { getApiUrl } from './utils/api-client';
import { getPaginatedResource } from './utils/pagination';

const log = debug('twilio-serverless-api:assets');

Expand Down Expand Up @@ -149,7 +150,7 @@ async function createAssetVersion(
`Services/${serviceSid}/Assets/${asset.sid}/Versions`,
{
responseType: 'text',
prefixUrl: 'https://serverless-upload.twilio.com/v1',
prefixUrl: getApiUrl(client.twilioClientConfig, 'serverless-upload'),
body: form,
}
);
Expand Down
5 changes: 3 additions & 2 deletions src/api/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import {
VersionResource,
} from '../types';
import { getContentType } from '../utils/content-type';
import { getPaginatedResource } from './utils/pagination';
import { ClientApiError } from '../utils/error';
import { getApiUrl } from './utils/api-client';
import { getPaginatedResource } from './utils/pagination';

const log = debug('twilio-serverless-api:functions');

Expand Down Expand Up @@ -148,7 +149,7 @@ async function createFunctionVersion(
`Services/${serviceSid}/Functions/${fn.sid}/Versions`,
{
responseType: 'text',
prefixUrl: 'https://serverless-upload.twilio.com/v1',
prefixUrl: getApiUrl(client.twilioClientConfig, 'serverless-upload'),
body: form,
}
);
Expand Down
65 changes: 65 additions & 0 deletions src/api/utils/__tests__/api-client.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { DEFAULT_TEST_CLIENT_CONFIG } from '../../../__fixtures__/base-fixtures';
import { getApiUrl } from '../api-client';

describe('getApiUrl', () => {
beforeEach(() => {
delete process.env.TWILIO_EDGE;
delete process.env.TWILIO_REGION;
});

test('returns base URL with standard options', () => {
const url = getApiUrl(DEFAULT_TEST_CLIENT_CONFIG);
expect(url).toBe('https://serverless.twilio.com/v1');
});

test('handles different product base urls', () => {
const url = getApiUrl(DEFAULT_TEST_CLIENT_CONFIG, 'serverless-upload');
expect(url).toBe('https://serverless-upload.twilio.com/v1');
});

test('works with region config', () => {
const url = getApiUrl({ ...DEFAULT_TEST_CLIENT_CONFIG, region: 'dev' });
expect(url).toBe('https://serverless.dev.twilio.com/v1');
});

test('works with region config and a product', () => {
const url = getApiUrl(
{ ...DEFAULT_TEST_CLIENT_CONFIG, region: 'dev' },
'serverless-upload'
);
expect(url).toBe('https://serverless-upload.dev.twilio.com/v1');
});

test('works with edge config', () => {
const url = getApiUrl({ ...DEFAULT_TEST_CLIENT_CONFIG, edge: 'sydney' });
expect(url).toBe('https://serverless.sydney.twilio.com/v1');
});

test('works with region and edge config', () => {
const url = getApiUrl({
...DEFAULT_TEST_CLIENT_CONFIG,
edge: 'sydney',
region: 'au1',
});
expect(url).toBe('https://serverless.sydney.au1.twilio.com/v1');
});

test('works with region env variable', () => {
process.env.TWILIO_REGION = 'stage';
const url = getApiUrl(DEFAULT_TEST_CLIENT_CONFIG);
expect(url).toBe('https://serverless.stage.twilio.com/v1');
});

test('works with edge env variable', () => {
process.env.TWILIO_EDGE = 'sydney';
const url = getApiUrl(DEFAULT_TEST_CLIENT_CONFIG);
expect(url).toBe('https://serverless.sydney.twilio.com/v1');
});

test('works with region & edge env variable', () => {
process.env.TWILIO_EDGE = 'sydney';
process.env.TWILIO_REGION = 'au2';
const url = getApiUrl(DEFAULT_TEST_CLIENT_CONFIG);
expect(url).toBe('https://serverless.sydney.au2.twilio.com/v1');
});
});
14 changes: 14 additions & 0 deletions src/api/utils/api-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ClientConfig } from '../../types';

export function getApiUrl(
config: ClientConfig,
product = 'serverless',
apiVersion = 'v1'
): string {
const configEdge = config.edge || process.env.TWILIO_EDGE;
const configRegion = config.region || process.env.TWILIO_REGION;

const edge = configEdge ? `${configEdge}.` : '';
const region = configRegion ? `${configRegion}.` : '';
return `https://${product}.${edge}${region}twilio.com/${apiVersion}`;
}
16 changes: 9 additions & 7 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import debug from 'debug';
import events from 'events';
import got from './got';
import { getOrCreateAssetResources, uploadAsset } from './api/assets';
import {
activateBuild,
Expand All @@ -22,15 +21,19 @@ import {
} from './api/environments';
import {
getOrCreateFunctionResources,
uploadFunction,
isFunctionSid,
listFunctionResources,
uploadFunction,
} from './api/functions';
import { listOnePageLogResources } from './api/logs';
import { createService, findServiceSid, listServices } from './api/services';
import { getApiUrl } from './api/utils/api-client';
import {
listVariablesForEnvironment,
setEnvironmentVariables,
} from './api/variables';
import got from './got';
import { LogsStream } from './streams/logs';
import {
ActivateConfig,
ActivateResult,
Expand All @@ -46,23 +49,22 @@ import {
LogsConfig,
} from './types';
import { DeployStatus } from './types/consts';
import { getListOfFunctionsAndAssets, SearchConfig } from './utils/fs';
import { LogsStream } from './streams/logs';
import { listOnePageLogResources } from './api/logs';
import { ClientApiError, convertApiErrorsAndThrow } from './utils/error';
import { getListOfFunctionsAndAssets, SearchConfig } from './utils/fs';

const log = debug('twilio-serverless-api:client');

export function createGotClient(config: ClientConfig): GotClient {
const client = got.extend({
prefixUrl: 'https://serverless.twilio.com/v1',
prefixUrl: getApiUrl(config),
responseType: 'json',
username: config.accountSid,
password: config.authToken,
headers: {
'User-Agent': 'twilio-serverless-api',
},
});
}) as GotClient;
client.twilioClientConfig = config;
return client;
}

Expand Down
8 changes: 8 additions & 0 deletions src/types/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@ export type ClientConfig = {
* Twilio Auth Token or API Secret
*/
authToken: string;
/**
* Twilio Region
*/
region?: string;
/**
* Twilio Edge
*/
edge?: string;
};
5 changes: 4 additions & 1 deletion src/types/generic.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/** @module @twilio-labs/serverless-api */

import { Got } from 'got';
import { ClientConfig } from './client';

export type GotClient = Got;
export type GotClient = Got & {
twilioClientConfig: ClientConfig;
};

export type EnvironmentVariables = {
[key: string]: string | undefined;
Expand Down