Skip to content

Commit

Permalink
Merge branch 'DEVEXP-416_New-pagination-type-for-EST-lists' into DEVE…
Browse files Browse the repository at this point in the history
…XP-406_Add-support-for-SIP-Trunks
  • Loading branch information
asein-sinch committed Apr 26, 2024
2 parents deca830 + d200245 commit 42cddef
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 29 deletions.
34 changes: 21 additions & 13 deletions packages/elastic-sip-trunking/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,20 @@ const credentials: UnifiedCredentials = {
keySecret: 'KEY_SECRET',
};

// Access the 'fax' service registered on the Sinch Client
// Access the 'elasticSipTrunking' service registered on the Sinch Client
const sinch = new SinchClient(credentials);
const elasticSipTrunkingService: ElasticSipTrunkingService = sinch.elasticSipTrunking;

// Build the request data
const requestData: ElasticSipTrunking.InterfaceTBD = {
const requestData: ElasticSipTrunking.CreateSipTrunkRequestData = {
createSipTrunkRequestBody: {
name: 'Acme Trunk',
hostName: 'acme-domain-1',
}
};

// Access the 'elasticSipTrunking' service registered on the Sinch Client
const result = await sinch.elasticSipTrunking.tag.method(requestData);
// Use the 'elasticSipTrunking' service registered on the Sinch Client
const result = await sinch.elasticSipTrunking.sipTrunks.create(requestData);
```

### Standalone
Expand All @@ -82,11 +86,15 @@ const credentials: UnifiedCredentials = {
const elasticSipTrunkingService = new ElasticSipTrunkingService(options);

// Build the request data
const requestData: ElasticSipTrunking.InterfaceTBD = {
const requestData: ElasticSipTrunking.CreateSipTrunkRequestData = {
createSipTrunkRequestBody: {
name: 'Acme Trunk',
hostName: 'acme-domain-1',
}
};

// Use the standalone declaration of the 'elasticSipTrunking' service
const result = await elasticSipTrunkingService.tag.method(requestData);
const result = await elasticSipTrunkingService.sipTrunks.create(requestData);
```

## Promises
Expand All @@ -95,18 +103,18 @@ All the methods that interact with the Sinch APIs use Promises. You can use `awa

```typescript
// Method 1: Wait for the Promise to complete
let result: ElasticSipTrunking.ResultInterfaceTBD;
let result: ElasticSipTrunking.SipTrunk;
try {
result = await elasticSipTrunkingService.tag.method(requestData);
console.log(``);
result = await elasticSipTrunkingService.sipTrunks.create(requestData);
console.log(`SIP trunk successfully created at '${response.createTime.toISOString()}' with the id '${response.id}'`);
} catch (error: any) {
console.error(`ERROR ${error.statusCode}: `);
console.error(`ERROR ${error.statusCode}: Impossible to create a SIP Trunk with the hostname '${requestData.hostName}'`);
}

// Method 2: Resolve the promise
elasticSipTrunkingService.tag.method(requestData)
.then(response => console.log(``))
.catch(error => console.error(`ERROR ${error.statusCode}: `));
elasticSipTrunkingService.sipTrunks.create(requestData)
.then(response => console.log(`SIP trunk successfully created at '${response.createTime.toISOString()}' with the id '${response.id}'`))
.catch(error => console.error(`ERROR ${error.statusCode}: Impossible to create a SIP Trunk with the hostname '${requestData.hostName}'`));
```

## Contact
Expand Down
3 changes: 1 addition & 2 deletions packages/elastic-sip-trunking/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
"description": "Sinch Elastic SIP Trunking API",
"homepage": "",
"repository": {
"type": "git",
"url": ""
"type": "git"
},
"license": "Apache-2.0",
"author": "Sinch",
Expand Down
5 changes: 5 additions & 0 deletions packages/sdk-client/src/api/api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import FormData = require('form-data');

export enum PaginationEnum {
NONE,
/** Used by the Numbers API */
TOKEN,
/** used by the SMS API */
PAGE,
/** used by the Elastic SIP Trunking API */
PAGE2,
/** used by the Fax API */
PAGE3
}
export interface ApiListPromise<T> extends Promise<PageResult<T>>, AsyncIterableIterator<T> {
Expand Down
91 changes: 77 additions & 14 deletions packages/sdk-client/src/client/api-client-pagination-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,23 @@ export const createNextPageMethod = <T>(
nextPageValue: string,
): ApiListPromise<T> => {
let newParams;
if (context.pagination === PaginationEnum.TOKEN) {
switch (context.pagination) {
case PaginationEnum.TOKEN:
newParams = {
pageToken: nextPageValue,
};
} else if (context.pagination === PaginationEnum.PAGE || context.pagination === PaginationEnum.PAGE3) {
break;
case PaginationEnum.PAGE:
case PaginationEnum.PAGE2:
case PaginationEnum.PAGE3:
newParams = {
page: nextPageValue,
};
} else {
break;
default:
throw new Error(`Error: the pagination method (${context.pagination}) is not supported`);
}

const pageResultPromise = updateQueryParamsAndSendRequest<T>(apiClient, newParams, requestOptions, context);

const requestOptionsPromise = new Promise<RequestOptions>((resolve) => {
Expand All @@ -166,7 +172,12 @@ export function hasMore(
if (context.pagination === PaginationEnum.PAGE) {
const requestedPageSize = context.requestOptions.queryParams?.page_size;
const pageSize: number = requestedPageSize ? parseInt(requestedPageSize) : response.page_size;
return checkIfThereAreMorePages(response, pageSize);
return checkIfThereAreMorePages(response, pageSize, PaginationEnum.PAGE);
}
if (context.pagination === PaginationEnum.PAGE2) {
const requestedPageSize = context.requestOptions.queryParams?.pageSize;
const pageSize: number = requestedPageSize ? parseInt(requestedPageSize) : response.pageSize;
return checkIfThereAreMorePages(response, pageSize, PaginationEnum.PAGE2);
}
if (context.pagination === PaginationEnum.PAGE3) {
return response.pageNumber < response.totalPages;
Expand All @@ -186,7 +197,7 @@ export function calculateNextPage(
const nextPage = currentPage + 1;
return nextPage.toString();
}
if (context.pagination === PaginationEnum.PAGE3) {
if (context.pagination === PaginationEnum.PAGE2 || context.pagination === PaginationEnum.PAGE3) {
const currentPage: number = response.pageNumber || 1;
const nextPage = currentPage + 1;
return nextPage.toString();
Expand Down Expand Up @@ -230,7 +241,9 @@ export const buildPageResultPromise = async <T>(
});
};

interface WithPagination {
interface WithPagination extends WithPagination_PAGE, WithPagination_PAGE2 {}

interface WithPagination_PAGE {
/** The total number of entries matching the given filters. */
count?: number;
/** The requested page. */
Expand All @@ -239,13 +252,30 @@ interface WithPagination {
page_size?: number;
}

const checkIfThereAreMorePages = (response: WithPagination, requestedPageSize: number | undefined): boolean => {
const lastPageNumber = calculateLastPageValue(response, requestedPageSize);
interface WithPagination_PAGE2 {
/** The total number of entries matching the given filters. */
totalItems?: number;
/** The requested page. */
pageNumber?: number;
/** The number of entries returned in this request. */
pageSize?: number;
}

const checkIfThereAreMorePages = (
response: WithPagination,
requestedPageSize: number | undefined,
paginationType: PaginationEnum,
): boolean => {
const lastPageNumber = calculateLastPageValue(response, requestedPageSize, paginationType);
return response.page! < lastPageNumber;
};

const calculateLastPageValue = (response: WithPagination, requestedPageSize: number | undefined): number => {
if (invalidatePaginationDataFromResponse(response)) {
const calculateLastPageValue = (
response: WithPagination,
requestedPageSize: number | undefined,
paginationType: PaginationEnum,
): number => {
if (invalidatePaginationDataFromResponse(response, paginationType)) {
throw new Error(`Impossible to calculate the last page value with the following parameters: count=${response.count}, page=${response.page}, page_size=${response.page_size}`);
}
if (response.page_size === 0) {
Expand All @@ -258,13 +288,46 @@ const calculateLastPageValue = (response: WithPagination, requestedPageSize: num
return Math.ceil(itemCount / pageSize) - 1;
};

const invalidatePaginationDataFromResponse = (response: WithPagination): boolean => {
const currentPage = response.page;
const pageSize = response.page_size;
const itemCount = response.count;
const invalidatePaginationDataFromResponse = (response: WithPagination, paginationType: PaginationEnum): boolean => {
const currentPage = getCurrentPage(response, paginationType);
const pageSize = getPageSize(response, paginationType);
const itemCount = getItemCount(response, paginationType);
return !isNumber(currentPage) || !isNumber(pageSize) || !isNumber(itemCount);
};

const getCurrentPage = (response: WithPagination, paginationType: PaginationEnum): number | undefined => {
switch (paginationType) {
case PaginationEnum.PAGE:
return response.page;
case PaginationEnum.PAGE2:
return response.pageNumber;
default:
return undefined;
}
};

const getPageSize = (response: WithPagination, paginationType: PaginationEnum): number | undefined => {
switch (paginationType) {
case PaginationEnum.PAGE:
return response.page_size;
case PaginationEnum.PAGE2:
return response.pageSize;
default:
return undefined;
}
};

const getItemCount = (response: WithPagination, paginationType: PaginationEnum): number | undefined => {
switch (paginationType) {
case PaginationEnum.PAGE:
return response.count;
case PaginationEnum.PAGE2:
return response.totalItems;
default:
return undefined;
}
};

const isNumber = (value: any) => {
return typeof value === 'number' && !isNaN(value);
};

0 comments on commit 42cddef

Please sign in to comment.