@azure/search-documents
Version:
Azure client library to use AI Search for node.js and browser.
143 lines • 5.19 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { createRestError } from "@azure-rest/core-client";
import { RestError } from "@azure/core-rest-pipeline";
/**
* Helper to paginate results in a generic way and return a PagedAsyncIterableIterator
*/
export function buildPagedAsyncIterator(client, getInitialResponse, processResponseBody, expectedStatuses, options = {}) {
const itemName = options.itemName ?? "value";
const nextLinkName = options.nextLinkName ?? "nextLink";
const nextLinkMethod = options.nextLinkMethod ?? "GET";
const apiVersion = options.apiVersion;
const pagedResult = {
getPage: async (pageLink) => {
let result;
if (pageLink === undefined) {
result = await getInitialResponse();
}
else {
const resolvedPageLink = apiVersion ? addApiVersionToUrl(pageLink, apiVersion) : pageLink;
result =
nextLinkMethod === "POST"
? await client.pathUnchecked(resolvedPageLink).post()
: await client.pathUnchecked(resolvedPageLink).get();
}
checkPagingRequest(result, expectedStatuses);
const results = await processResponseBody(result);
const nextLink = getNextLink(results, nextLinkName);
const values = getElements(results, itemName);
return {
page: values,
nextPageLink: nextLink,
};
},
byPage: (settings) => {
const { continuationToken } = settings ?? {};
return getPageAsyncIterator(pagedResult, {
pageLink: continuationToken,
});
},
};
return getPagedAsyncIterator(pagedResult);
}
/**
* returns an async iterator that iterates over results. It also has a `byPage`
* method that returns pages of items at once.
*
* @param pagedResult - an object that specifies how to get pages.
* @returns a paged async iterator that iterates over results.
*/
function getPagedAsyncIterator(pagedResult) {
const iter = getItemAsyncIterator(pagedResult);
return {
next() {
return iter.next();
},
[Symbol.asyncIterator]() {
return this;
},
byPage: pagedResult?.byPage ??
((settings) => {
const { continuationToken } = settings ?? {};
return getPageAsyncIterator(pagedResult, {
pageLink: continuationToken,
});
}),
};
}
async function* getItemAsyncIterator(pagedResult) {
const pages = getPageAsyncIterator(pagedResult);
for await (const page of pages) {
yield* page;
}
}
async function* getPageAsyncIterator(pagedResult, options = {}) {
const { pageLink } = options;
let response = await pagedResult.getPage(pageLink ?? pagedResult.firstPageLink);
if (!response) {
return;
}
let result = response.page;
result.continuationToken = response.nextPageLink;
yield result;
while (response.nextPageLink) {
response = await pagedResult.getPage(response.nextPageLink);
if (!response) {
return;
}
result = response.page;
result.continuationToken = response.nextPageLink;
yield result;
}
}
/**
* Gets for the value of nextLink in the body
*/
function getNextLink(body, nextLinkName) {
if (!nextLinkName) {
return undefined;
}
const nextLink = body[nextLinkName];
if (typeof nextLink !== "string" && typeof nextLink !== "undefined" && nextLink !== null) {
throw new RestError(`Body Property ${nextLinkName} should be a string or undefined or null but got ${typeof nextLink}`);
}
if (nextLink === null) {
return undefined;
}
return nextLink;
}
/**
* Gets the elements of the current request in the body.
*/
function getElements(body, itemName) {
const value = body[itemName];
if (!Array.isArray(value)) {
throw new RestError(`Couldn't paginate response\n Body doesn't contain an array property with name: ${itemName}`);
}
return value ?? [];
}
/**
* Checks if a request failed
*/
function checkPagingRequest(response, expectedStatuses) {
if (!expectedStatuses.includes(response.status)) {
throw createRestError(`Pagination failed with unexpected statusCode ${response.status}`, response);
}
}
/**
* Adds the api-version query parameter on a URL if it's not present.
* @param url - the URL to modify
* @param apiVersion - the API version to set
* @returns - the URL with the api-version query parameter set
*/
function addApiVersionToUrl(url, apiVersion) {
// The base URL is only used for parsing and won't appear in the returned URL
const urlObj = new URL(url, "https://microsoft.com");
if (!urlObj.searchParams.get("api-version")) {
// Append one if there is no apiVersion
return `${url}${Array.from(urlObj.searchParams.keys()).length > 0 ? "&" : "?"}api-version=${apiVersion}`;
}
return url;
}
//# sourceMappingURL=pagingHelpers.js.map