From ffbc4b6c803412d67f6ac5441f8959baef371697 Mon Sep 17 00:00:00 2001 From: Rodrigo Mansueli Nunes Date: Tue, 19 Dec 2023 10:45:13 -0300 Subject: [PATCH 1/9] feat: add regional calls in the functions library --- src/FunctionsClient.ts | 6 +++++- src/types.ts | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/FunctionsClient.ts b/src/FunctionsClient.ts index 79968b5..d603fee 100644 --- a/src/FunctionsClient.ts +++ b/src/FunctionsClient.ts @@ -11,6 +11,7 @@ import { export class FunctionsClient { protected url: string protected headers: Record + protected region: string protected fetch: Fetch constructor( @@ -25,6 +26,7 @@ export class FunctionsClient { ) { this.url = url this.headers = headers + this.region = 'any' this.fetch = resolveFetch(customFetch) } @@ -47,8 +49,10 @@ export class FunctionsClient { ): Promise> { try { const { headers, method, body: functionArgs } = options - let _headers: Record = {} + if (this.region !== 'any') { + _headers['x-region'] = this.region + } let body: any if ( functionArgs && diff --git a/src/types.ts b/src/types.ts index 9e0646b..1be4cc0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -50,6 +50,24 @@ export type FunctionInvokeOptions = { * The HTTP verb of the request */ method?: 'POST' | 'GET' | 'PUT' | 'PATCH' | 'DELETE' + /** + * The Region to invoke the function in. + */ + region?: 'any' + | 'ap-northeast-1' + | 'ap-northeast-2' + | 'ap-south-1' + | 'ap-southeast-1' + | 'ap-southeast-2' + | 'ca-central-1' + | 'eu-central-1' + | 'eu-west-1' + | 'eu-west-2' + | 'eu-west-3' + | 'sa-east-1' + | 'us-east-1' + | 'us-west-1' + | 'us-west-2' /** * The body of the request. */ From eaac10d88e72bf37f590187013dcc5b370cec799 Mon Sep 17 00:00:00 2001 From: Rodrigo Mansueli Nunes Date: Tue, 19 Dec 2023 10:49:01 -0300 Subject: [PATCH 2/9] prettier --- src/types.ts | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/types.ts b/src/types.ts index 1be4cc0..adb3a51 100644 --- a/src/types.ts +++ b/src/types.ts @@ -53,21 +53,22 @@ export type FunctionInvokeOptions = { /** * The Region to invoke the function in. */ - region?: 'any' - | 'ap-northeast-1' - | 'ap-northeast-2' - | 'ap-south-1' - | 'ap-southeast-1' - | 'ap-southeast-2' - | 'ca-central-1' - | 'eu-central-1' - | 'eu-west-1' - | 'eu-west-2' - | 'eu-west-3' - | 'sa-east-1' - | 'us-east-1' - | 'us-west-1' - | 'us-west-2' + region?: + | 'any' + | 'ap-northeast-1' + | 'ap-northeast-2' + | 'ap-south-1' + | 'ap-southeast-1' + | 'ap-southeast-2' + | 'ca-central-1' + | 'eu-central-1' + | 'eu-west-1' + | 'eu-west-2' + | 'eu-west-3' + | 'sa-east-1' + | 'us-east-1' + | 'us-west-1' + | 'us-west-2' /** * The body of the request. */ From 19512a44aa3b8e4ea89a825899a4e1b2223368af Mon Sep 17 00:00:00 2001 From: Rodrigo Mansueli Nunes Date: Tue, 9 Jan 2024 17:03:35 -0300 Subject: [PATCH 3/9] Update types.ts --- src/types.ts | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/types.ts b/src/types.ts index adb3a51..3fca51c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -40,6 +40,24 @@ export class FunctionsHttpError extends FunctionsError { super('Edge Function returned a non-2xx status code', 'FunctionsHttpError', context) } } +// Define the enum for the 'region' property +export enum FunctionRegion { + Any = 'any', + ApNortheast1 = 'ap-northeast-1', + ApNortheast2 = 'ap-northeast-2', + ApSouth1 = 'ap-south-1', + ApSoutheast1 = 'ap-southeast-1', + ApSoutheast2 = 'ap-southeast-2', + CaCentral1 = 'ca-central-1', + EuCentral1 = 'eu-central-1', + EuWest1 = 'eu-west-1', + EuWest2 = 'eu-west-2', + EuWest3 = 'eu-west-3', + SaEast1 = 'sa-east-1', + UsEast1 = 'us-east-1', + UsWest1 = 'us-west-1', + UsWest2 = 'us-west-2', +} export type FunctionInvokeOptions = { /** @@ -53,22 +71,7 @@ export type FunctionInvokeOptions = { /** * The Region to invoke the function in. */ - region?: - | 'any' - | 'ap-northeast-1' - | 'ap-northeast-2' - | 'ap-south-1' - | 'ap-southeast-1' - | 'ap-southeast-2' - | 'ca-central-1' - | 'eu-central-1' - | 'eu-west-1' - | 'eu-west-2' - | 'eu-west-3' - | 'sa-east-1' - | 'us-east-1' - | 'us-west-1' - | 'us-west-2' + region?: FunctionRegion; /** * The body of the request. */ From 6313d3965de30b079bd9b8ce693307b38f04e901 Mon Sep 17 00:00:00 2001 From: Rodrigo Mansueli Nunes Date: Mon, 22 Jan 2024 11:50:43 -0300 Subject: [PATCH 4/9] Update params.spec.ts --- test/spec/params.spec.ts | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/test/spec/params.spec.ts b/test/spec/params.spec.ts index ee8c9be..f10a86a 100644 --- a/test/spec/params.spec.ts +++ b/test/spec/params.spec.ts @@ -7,7 +7,7 @@ import { sign } from 'jsonwebtoken' import { ContentType } from 'allure-js-commons' import { FunctionsClient } from '../../src/index' - +import { FunctionRegion } from '../../src/types' import { Relay, runRelay } from '../relay/container' import { attach, log } from '../utils/jest-custom-reporter' import { str2ab } from '../utils/binaries' @@ -146,6 +146,29 @@ describe('params reached to function', () => { ).toBe(true) }) + test('invoke mirror with invoke header and valid region', async () => { + /** + * @feature headers + */ + log('create FunctionsClient') + const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`) + + log('invoke mirror') + const customHeader = nanoid(); + const validRegion = FunctionRegion.ApNortheast1; + + const { data, error } = await fclient.invoke('mirror', { + headers: { + 'custom-header': customHeader, + Authorization: `Bearer ${apiKey}`, + }, + region: validRegion + }) + + log('assert no error') + expect(data).not.toBeNull() + }) + test('invoke mirror with body formData', async () => { /** * @feature body From d4837e031840a41874342ba9819ed7a87226db04 Mon Sep 17 00:00:00 2001 From: Rodrigo Mansueli Nunes Date: Mon, 22 Jan 2024 11:59:31 -0300 Subject: [PATCH 5/9] Update params.spec.ts --- test/spec/params.spec.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/spec/params.spec.ts b/test/spec/params.spec.ts index f10a86a..3c3a7b4 100644 --- a/test/spec/params.spec.ts +++ b/test/spec/params.spec.ts @@ -169,6 +169,29 @@ describe('params reached to function', () => { expect(data).not.toBeNull() }) + test('invoke mirror with invoke header and valid region', async () => { + /** + * @feature headers + */ + log('create FunctionsClient') + const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`) + + log('invoke mirror') + const customHeader = nanoid(); + const validRegion = FunctionRegion.Any + + const { data, error } = await fclient.invoke('mirror', { + headers: { + 'custom-header': customHeader, + Authorization: `Bearer ${apiKey}`, + 'x-region': validRegion + } + }) + + log('assert no error') + expect(data).not.toBeNull() + }) + test('invoke mirror with body formData', async () => { /** * @feature body From c7d7b172286ae20cfa18942ca399e1dd9dc958d8 Mon Sep 17 00:00:00 2001 From: Rodrigo Mansueli Nunes Date: Mon, 22 Jan 2024 12:02:40 -0300 Subject: [PATCH 6/9] Update params.spec.ts --- test/spec/params.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/params.spec.ts b/test/spec/params.spec.ts index 3c3a7b4..becd0cb 100644 --- a/test/spec/params.spec.ts +++ b/test/spec/params.spec.ts @@ -178,7 +178,7 @@ describe('params reached to function', () => { log('invoke mirror') const customHeader = nanoid(); - const validRegion = FunctionRegion.Any + const validRegion = FunctionRegion.EuWest1; const { data, error } = await fclient.invoke('mirror', { headers: { From e4a86d8ae9da9f4ee69de41e9915fc91d47eab25 Mon Sep 17 00:00:00 2001 From: egor-romanov Date: Wed, 31 Jan 2024 01:58:22 +0400 Subject: [PATCH 7/9] fix: set region on invoke and in constructor --- src/FunctionsClient.ts | 15 +++-- test/spec/params.spec.ts | 120 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 123 insertions(+), 12 deletions(-) diff --git a/src/FunctionsClient.ts b/src/FunctionsClient.ts index d603fee..6e044db 100644 --- a/src/FunctionsClient.ts +++ b/src/FunctionsClient.ts @@ -6,12 +6,13 @@ import { FunctionsRelayError, FunctionsResponse, FunctionInvokeOptions, + FunctionRegion, } from './types' export class FunctionsClient { protected url: string protected headers: Record - protected region: string + protected region: FunctionRegion protected fetch: Fetch constructor( @@ -19,14 +20,16 @@ export class FunctionsClient { { headers = {}, customFetch, + region = FunctionRegion.Any, }: { headers?: Record customFetch?: Fetch + region?: FunctionRegion } = {} ) { this.url = url this.headers = headers - this.region = 'any' + this.region = region this.fetch = resolveFetch(customFetch) } @@ -50,8 +53,12 @@ export class FunctionsClient { try { const { headers, method, body: functionArgs } = options let _headers: Record = {} - if (this.region !== 'any') { - _headers['x-region'] = this.region + let { region } = options + if (!region) { + region = this.region + } + if (region && region !== 'any') { + _headers['x-region'] = region } let body: any if ( diff --git a/test/spec/params.spec.ts b/test/spec/params.spec.ts index becd0cb..1ba19a4 100644 --- a/test/spec/params.spec.ts +++ b/test/spec/params.spec.ts @@ -154,21 +154,125 @@ describe('params reached to function', () => { const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`) log('invoke mirror') - const customHeader = nanoid(); - const validRegion = FunctionRegion.ApNortheast1; + const customHeader = nanoid() + const validRegion = FunctionRegion.ApNortheast1 const { data, error } = await fclient.invoke('mirror', { headers: { 'custom-header': customHeader, Authorization: `Bearer ${apiKey}`, }, - region: validRegion + region: validRegion, }) log('assert no error') - expect(data).not.toBeNull() + const expected = { + url: 'http://localhost:8000/mirror', + method: 'POST', + headers: data?.headers ?? [], + body: '', + } + expect(data).toEqual(expected) + attach( + 'check headers from function', + `expected to include: ${['custom-header', customHeader]}\n actual: ${JSON.stringify( + data?.headers + )}`, + ContentType.TEXT + ) + console.log(data?.headers) + expect( + (data?.headers as [Array]).filter(([k, v]) => k === 'x-region' && v === validRegion) + .length > 0 + ).toBe(true) + }) + + test('invoke with region overrides region in the client', async () => { + /** + * @feature headers + */ + log('create FunctionsClient') + const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`, { + region: FunctionRegion.ApNortheast1, + }) + + log('invoke mirror') + const customHeader = nanoid() + const validRegion = FunctionRegion.ApSoutheast1 + + const { data, error } = await fclient.invoke('mirror', { + headers: { + 'custom-header': customHeader, + Authorization: `Bearer ${apiKey}`, + }, + region: validRegion, + }) + + log('assert no error') + const expected = { + url: 'http://localhost:8000/mirror', + method: 'POST', + headers: data?.headers ?? [], + body: '', + } + expect(data).toEqual(expected) + attach( + 'check headers from function', + `expected to include: ${['custom-header', customHeader]}\n actual: ${JSON.stringify( + data?.headers + )}`, + ContentType.TEXT + ) + console.log(data?.headers) + expect( + (data?.headers as [Array]).filter(([k, v]) => k === 'x-region' && v === validRegion) + .length > 0 + ).toBe(true) + }) + + test('invoke with region overrides region in the client', async () => { + /** + * @feature headers + */ + log('create FunctionsClient') + const validRegion = FunctionRegion.ApSoutheast1 + const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`, { + region: validRegion, + }) + + log('invoke mirror') + const customHeader = nanoid() + + const { data, error } = await fclient.invoke('mirror', { + headers: { + 'custom-header': customHeader, + Authorization: `Bearer ${apiKey}`, + }, + }) + + log('assert no error') + const expected = { + url: 'http://localhost:8000/mirror', + method: 'POST', + headers: data?.headers ?? [], + body: '', + } + expect(data).toEqual(expected) + attach( + 'check headers from function', + `expected to include: ${['custom-header', customHeader]}\n actual: ${JSON.stringify( + data?.headers + )}`, + ContentType.TEXT + ) + console.log(data?.headers) + expect( + (data?.headers as [Array]).filter(([k, v]) => k === 'x-region' && v === validRegion) + .length > 0 + ).toBe(true) }) + // todo: update test to check for the correct header value test('invoke mirror with invoke header and valid region', async () => { /** * @feature headers @@ -177,15 +281,15 @@ describe('params reached to function', () => { const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`) log('invoke mirror') - const customHeader = nanoid(); - const validRegion = FunctionRegion.EuWest1; + const customHeader = nanoid() + const validRegion = FunctionRegion.EuWest1 const { data, error } = await fclient.invoke('mirror', { headers: { 'custom-header': customHeader, Authorization: `Bearer ${apiKey}`, - 'x-region': validRegion - } + 'x-region': validRegion, + }, }) log('assert no error') From af5e70779c97f254d12d9159912357f74935efed Mon Sep 17 00:00:00 2001 From: Rodrigo Mansueli Nunes Date: Tue, 30 Jan 2024 19:05:13 -0300 Subject: [PATCH 8/9] Update params.spec.ts --- test/spec/params.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/spec/params.spec.ts b/test/spec/params.spec.ts index 1ba19a4..bcf6c71 100644 --- a/test/spec/params.spec.ts +++ b/test/spec/params.spec.ts @@ -272,7 +272,6 @@ describe('params reached to function', () => { ).toBe(true) }) - // todo: update test to check for the correct header value test('invoke mirror with invoke header and valid region', async () => { /** * @feature headers @@ -293,7 +292,10 @@ describe('params reached to function', () => { }) log('assert no error') - expect(data).not.toBeNull() + expect( + (data?.headers as [Array]).filter(([k, v]) => k === 'x-region' && v === FunctionRegion.EuWest1) + .length > 0 + ).toBe(true) }) test('invoke mirror with body formData', async () => { From 4a5b2d366b2f65703b8ec921cb626ccffbd548c7 Mon Sep 17 00:00:00 2001 From: Rodrigo Mansueli Nunes Date: Tue, 30 Jan 2024 19:41:03 -0300 Subject: [PATCH 9/9] update tests --- test/spec/params.spec.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/spec/params.spec.ts b/test/spec/params.spec.ts index bcf6c71..63c1786 100644 --- a/test/spec/params.spec.ts +++ b/test/spec/params.spec.ts @@ -146,7 +146,7 @@ describe('params reached to function', () => { ).toBe(true) }) - test('invoke mirror with invoke header and valid region', async () => { + test('invoke mirror set valid region on request', async () => { /** * @feature headers */ @@ -230,7 +230,7 @@ describe('params reached to function', () => { ).toBe(true) }) - test('invoke with region overrides region in the client', async () => { + test('starts client with default region, invoke reverts to any (no x-region header)', async () => { /** * @feature headers */ @@ -248,6 +248,7 @@ describe('params reached to function', () => { 'custom-header': customHeader, Authorization: `Bearer ${apiKey}`, }, + region: FunctionRegion.Any }) log('assert no error') @@ -268,32 +269,31 @@ describe('params reached to function', () => { console.log(data?.headers) expect( (data?.headers as [Array]).filter(([k, v]) => k === 'x-region' && v === validRegion) - .length > 0 + .length == 0 ).toBe(true) }) - test('invoke mirror with invoke header and valid region', async () => { + test('invoke region set only on the constructor', async () => { /** * @feature headers */ log('create FunctionsClient') - const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`) + const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`,{region: FunctionRegion.ApNortheast1}) log('invoke mirror') const customHeader = nanoid() - const validRegion = FunctionRegion.EuWest1 + const { data, error } = await fclient.invoke('mirror', { headers: { 'custom-header': customHeader, - Authorization: `Bearer ${apiKey}`, - 'x-region': validRegion, + Authorization: `Bearer ${apiKey}` }, }) log('assert no error') expect( - (data?.headers as [Array]).filter(([k, v]) => k === 'x-region' && v === FunctionRegion.EuWest1) + (data?.headers as [Array]).filter(([k, v]) => k === 'x-region' && v === FunctionRegion.ApNortheast1) .length > 0 ).toBe(true) })