* Lists a single batch of wiki pages across the project's wikis (optionally * filtered to one wiki). Uses a compound cursor of the form * `wiki|{wikiIndex}|{continuationToken}` so each wiki's `pagesbatch` pagination * is tracked independently.
( accessToken: string, organization: string, project: string, wikiFilter: string, maxItems: number, cursor: string | undefined, syncContext?: Record<string, unknown> )
| 1188 | * is tracked independently. |
| 1189 | */ |
| 1190 | async function listWikiPages( |
| 1191 | accessToken: string, |
| 1192 | organization: string, |
| 1193 | project: string, |
| 1194 | wikiFilter: string, |
| 1195 | maxItems: number, |
| 1196 | cursor: string | undefined, |
| 1197 | syncContext?: Record<string, unknown> |
| 1198 | ): Promise<ExternalDocumentList> { |
| 1199 | const allWikis = await resolveWikis(accessToken, organization, project, syncContext) |
| 1200 | const wikis = allWikis.filter((w) => wikiMatchesFilter(w, wikiFilter)) |
| 1201 | |
| 1202 | if (wikis.length === 0) { |
| 1203 | return { documents: [], hasMore: false } |
| 1204 | } |
| 1205 | |
| 1206 | let wikiIndex = 0 |
| 1207 | let continuationToken: string | undefined |
| 1208 | if (cursor) { |
| 1209 | // The continuation token is opaque and may contain `|`; keep everything after |
| 1210 | // the second separator intact instead of truncating it with a naive split. |
| 1211 | const firstSep = cursor.indexOf('|') |
| 1212 | const secondSep = firstSep === -1 ? -1 : cursor.indexOf('|', firstSep + 1) |
| 1213 | if (secondSep !== -1) { |
| 1214 | wikiIndex = Number(cursor.slice(firstSep + 1, secondSep)) || 0 |
| 1215 | const token = cursor.slice(secondSep + 1) |
| 1216 | continuationToken = token || undefined |
| 1217 | } |
| 1218 | } |
| 1219 | |
| 1220 | if (wikiIndex >= wikis.length) { |
| 1221 | return { documents: [], hasMore: false } |
| 1222 | } |
| 1223 | |
| 1224 | const wiki = wikis[wikiIndex] |
| 1225 | const url = `${ADO_BASE_URL}/${encodeURIComponent(organization)}/${encodeURIComponent(project)}/_apis/wiki/wikis/${encodeURIComponent(wiki.id)}/pagesbatch?api-version=${WIKI_API_VERSION}` |
| 1226 | const body: Record<string, unknown> = { top: WIKI_PAGE_BATCH_SIZE } |
| 1227 | if (continuationToken) body.continuationToken = continuationToken |
| 1228 | |
| 1229 | const response = await fetchWithRetry(url, { |
| 1230 | method: 'POST', |
| 1231 | headers: { |
| 1232 | Accept: 'application/json', |
| 1233 | 'Content-Type': 'application/json', |
| 1234 | Authorization: patAuthHeader(accessToken), |
| 1235 | }, |
| 1236 | body: JSON.stringify(body), |
| 1237 | }) |
| 1238 | if (!response.ok) { |
| 1239 | const errorText = await response.text().catch(() => '') |
| 1240 | logger.error('Failed to list Azure DevOps wiki pages', { |
| 1241 | wikiId: wiki.id, |
| 1242 | status: response.status, |
| 1243 | error: errorText, |
| 1244 | }) |
| 1245 | throw new Error(`Failed to list wiki pages: ${response.status}`) |
| 1246 | } |
| 1247 |
no test coverage detected