--- name: sp-query description: Спросить у SharePoint-тенанта реальные данные портала заявок через tools/sp — что отдаёт поисковый индекс (managed properties, Retrievable), сколько партиций и элементов в списках, произвольный KQL или REST. Использовать, когда ответ зависит от состояния тенанта, а не выводится из кода: «отдаётся ли поле через Search», «сколько на самом деле партиций», «почему запрос возвращает пусто», «проверь на живых данных». Не использовать для правки данных. --- # Запросы к SharePoint портала заявок ## Когда это нужно Рассуждать по коду можно долго и неправильно. Есть класс вопросов, где ответ живёт только в тенанте: - отдаёт ли индекс конкретное поле (`Retrievable`) — от этого зависит, можно ли заменить REST-дочитывание на `SelectProperties`; - сколько на самом деле партиций у типа заявки и сколько в них элементов (это переменная `P` во всех оценках числа запросов); - почему KQL возвращает пусто — не то имя managed property, не тот `Path`, нет прав; - как выглядит реальное значение поля (`AuthorOWSUSER` — не почта, а `почта | ФИО`). Если вопрос из этого списка — не гадай и не проси пользователя лезть в консоль браузера. Спроси тенант. ## Порядок действий ```bash cd tools/sp node sp.mjs status # сначала: есть ли вход вообще ``` `Logged out` → нужен вход. Он **интерактивный**: команда печатает код, который пользователь вводит в браузере сам. Запускать `login` в фоне бессмысленно — попроси пользователя выполнить его и вернуться. ```bash node sp.mjs login ``` Если ругается на `SP_APP_ID` — регистрация приложения не сделана, отправь пользователя в `tools/sp/README.md`, раздел «Разовая подготовка» (это разовая задача с admin consent, сам её не закроешь). Дальше: | команда | что отвечает | | --- | --- | | `node sp.mjs props` | отдаёт ли индекс поля заявки; `<нет в ответе>` / `` = не Retrievable | | `node sp.mjs lists` | портальные списки, их адреса и размеры — реальное число партиций | | `node sp.mjs search "" --select a,b --rows N` | тот же запрос, что шлёт портал | | `node sp.mjs get "/_api/web/..."` | произвольный GET | ## Что нельзя - **Не вводить пароли и секреты.** Вход только device code: код вводит пользователь. Если предлагаешь `--authType password` или `--secret` — ты делаешь неправильно. - **Не писать данные.** Инструмент читающий. Любая правка списков — отдельный разговор с пользователем, а не побочный эффект разбора. - **Не заводить app-only доступ по сертификату ради Search.** Он для этого не годится: `/_api/search/query` под app-only-токеном обычно не отдаёт ничего, поиску нужен пользовательский контекст. ## Грабли **`Queryable` ≠ `Retrievable`.** Разные флаги managed property. То, по чему получается фильтровать, не обязано приходить в ответе — и наоборот. Доказав одно, не считай доказанным другое: в этом проекте на этом уже спотыкались. **Имена managed properties нестандартные.** Суффикс по типу колонки: `OWSTEXT` (Text), `OWSCHCS` (Choice), `OWSUSER` (Person/Group). У колонок из группы колонок сайта добавляется префикс группы — поэтому существует `TansuSiteApproverOWSUSER`, а «ожидаемого» `ApproverOWSUSER` в схеме нет вовсе. Прежде чем сочинять имя, посмотри константы `MP_*` в `src/webparts/requestPortal/features/myRequests/myRequests.service.ts`. **Пустой результат ≠ свойство не работает.** Сначала проверь `Path` (адрес сайта, слеш на конце, регистр) и права — в этом проекте вывод «managed property сломана» однажды оказался артефактом задвоенного сегмента в тестовом `Path`. **Замер портала — это другое.** `tools/sp` отвечает на вопросы о данных. Чтобы понять, куда уходит время в самом портале, есть встроенный замер: `window.rpPerf = true` в консоли страницы (см. `src/webparts/requestPortal/shared/perfTrace.ts`), детали — `window.rpPerfDetail()`.