UNPKG

@azure/search-documents

Version:
143 lines 5.19 kB
// 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