import { AadHttpClient, HttpClientResponse } from '@microsoft/sp-http'; import { WebPartContext } from '@microsoft/sp-webpart-base'; import { APPROVAL_API_CLIENT_ID, DICTIONARY_API_BASE_URL } from '../config'; import { IProject, IProjectListResponse } from './models/IProject'; // GET /Project — справочник проектов. Ответ обёрнут в { items: [...] } и // ПАГИНИРОВАН, поэтому тянем ВСЕ страницы (иначе проекты за пределами первой // страницы не находятся в поиске пикера). Авторизация та же (AadHttpClient + // APPROVAL_API_CLIENT_ID, SSO текущего пользователя). const PAGE_SIZE = 500; const MAX_PAGES = 50; // страховка от бесконечного цикла (до 25 000 проектов) async function fetchProjects(context: WebPartContext): Promise { const client = await context.aadHttpClientFactory.getClient(APPROVAL_API_CLIENT_ID); const all: IProject[] = []; for (let page = 1; page <= MAX_PAGES; page++) { const response: HttpClientResponse = await client.get( `${DICTIONARY_API_BASE_URL}/Project?page=${page}&pageSize=${PAGE_SIZE}&includeDeleted=false`, AadHttpClient.configurations.v1 ); if (!response.ok) { throw new Error(`Project (page ${page}): ${response.status} ${response.statusText}`); } const body: IProjectListResponse = await response.json(); const items = body.items ?? []; all.push(...items); // Последняя страница — вернулось меньше запрошенного размера. if (items.length < PAGE_SIZE) break; } return all; } // Справочник в рамках сессии не меняется — грузим один раз и отдаём тот же // промис повторным вызовам (как в departments.service). let cache: Promise | undefined; export function getProjects(context: WebPartContext): Promise { if (!cache) { cache = fetchProjects(context).catch((e) => { cache = undefined; throw e; }); } return cache; }