* Resolves a SharePoint site URL like "contoso.sharepoint.com/sites/mysite" * into a Microsoft Graph siteId.
( accessToken: string, siteUrl: string, retryOptions?: Parameters<typeof fetchWithRetry>[2] )
| 70 | * into a Microsoft Graph siteId. |
| 71 | */ |
| 72 | async function resolveSiteId( |
| 73 | accessToken: string, |
| 74 | siteUrl: string, |
| 75 | retryOptions?: Parameters<typeof fetchWithRetry>[2] |
| 76 | ): Promise<{ id: string; displayName: string }> { |
| 77 | // Normalise: strip protocol, trailing slashes |
| 78 | const cleaned = siteUrl.replace(/^https?:\/\//, '').replace(/\/+$/, '') |
| 79 | |
| 80 | // Split into hostname and server-relative path |
| 81 | const firstSlash = cleaned.indexOf('/') |
| 82 | let hostname: string |
| 83 | let serverRelativePath: string |
| 84 | |
| 85 | if (firstSlash === -1) { |
| 86 | hostname = cleaned |
| 87 | serverRelativePath = '' |
| 88 | } else { |
| 89 | hostname = cleaned.slice(0, firstSlash) |
| 90 | serverRelativePath = cleaned.slice(firstSlash) |
| 91 | } |
| 92 | |
| 93 | // Graph endpoint: GET /sites/{hostname}:/{path} |
| 94 | const url = serverRelativePath |
| 95 | ? `${GRAPH_BASE}/sites/${hostname}:${serverRelativePath}` |
| 96 | : `${GRAPH_BASE}/sites/${hostname}` |
| 97 | |
| 98 | const response = await fetchWithRetry( |
| 99 | url, |
| 100 | { |
| 101 | method: 'GET', |
| 102 | headers: { |
| 103 | Authorization: `Bearer ${accessToken}`, |
| 104 | Accept: 'application/json', |
| 105 | }, |
| 106 | }, |
| 107 | retryOptions |
| 108 | ) |
| 109 | |
| 110 | if (!response.ok) { |
| 111 | const errorText = await response.text() |
| 112 | throw new Error( |
| 113 | `Failed to resolve SharePoint site "${siteUrl}": ${response.status} – ${errorText}` |
| 114 | ) |
| 115 | } |
| 116 | |
| 117 | const site = (await response.json()) as { id: string; displayName?: string } |
| 118 | logger.info('Resolved SharePoint site', { |
| 119 | siteUrl, |
| 120 | siteId: site.id, |
| 121 | displayName: site.displayName, |
| 122 | }) |
| 123 | return { id: site.id, displayName: site.displayName ?? '' } |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Downloads the text content of a drive item. |
no test coverage detected