| 1 | import type { Octokit as _Octokit } from "@octokit/rest"; |
| 2 | import * as Effect from "effect/Effect"; |
| 3 | import type { AuthError } from "../Auth/AuthProvider.ts"; |
| 4 | import { normalizeGitHubBaseUrl } from "./BaseUrl.ts"; |
| 5 | import { GitHubCredentials } from "./Credentials.ts"; |
| 6 | |
| 7 | export const Octokit: Effect.Effect<_Octokit, never, GitHubCredentials> = |
| 8 | Effect.gen(function* () { |
| 9 | const creds = yield* yield* GitHubCredentials; |
| 10 | return creds.octokit(); |
| 11 | }); |
| 12 | |
| 13 | /** |
| 14 | * An Octokit honoring a per-resource `baseUrl` prop. When `baseUrl` is set, |
| 15 | * it is normalized and used for this Octokit only (including an explicit |
| 16 | * `"github.com"`, which overrides an enterprise-wide credential host back to |
| 17 | * the default). When unset, falls back to the credentials' host — the |
| 18 | * `GitHub.providers({ baseUrl })` hard-code or the auth provider's resolved |
| 19 | * host. |
| 20 | */ |
| 21 | export const octokitFor = ( |
| 22 | baseUrl: string | undefined, |
| 23 | ): Effect.Effect<_Octokit, AuthError, GitHubCredentials> => |
| 24 | Effect.gen(function* () { |
| 25 | const creds = yield* yield* GitHubCredentials; |
| 26 | return baseUrl === undefined |
| 27 | ? creds.octokit() |
| 28 | : creds.octokit({ baseUrl: yield* normalizeGitHubBaseUrl(baseUrl) }); |
| 29 | }); |
| 30 | |
| 31 | /** |
| 32 | * The host a resource's `baseUrl` prop actually resolves to: the normalized |
| 33 | * prop when set, otherwise the credentials' host — which already reflects |
| 34 | * `GitHub.providers({ baseUrl })` or the auth provider's resolved host. |
| 35 | */ |
| 36 | export const effectiveGitHubBaseUrl = ( |
| 37 | baseUrl: string | undefined, |
| 38 | ): Effect.Effect<string | undefined, AuthError, GitHubCredentials> => |
| 39 | Effect.gen(function* () { |
| 40 | if (baseUrl !== undefined) { |
| 41 | return yield* normalizeGitHubBaseUrl(baseUrl); |
| 42 | } |
| 43 | const creds = yield* yield* GitHubCredentials; |
| 44 | return creds.baseUrl; |
| 45 | }); |
| 46 | |
| 47 | /** |
| 48 | * Whether a resource's EFFECTIVE GitHub host changed between deploys — used |
| 49 | * by resource `diff` implementations to decide replacement (a resource with |
| 50 | * the same name on a different GitHub instance is a different physical |
| 51 | * resource). |
| 52 | * |
| 53 | * Each side is resolved through the full fallback chain (explicit prop → |
| 54 | * `providers({ baseUrl })` → auth provider host) and normalized before |
| 55 | * comparing, so neither a cosmetic rewrite (`github.example.com` → |
| 56 | * `https://github.example.com/api/v3`) nor making the ambient default |
| 57 | * explicit (prop `undefined` → prop equal to the credentials' host) triggers |
| 58 | * a replacement — and dropping back to github.com from an enterprise-wide |
| 59 | * credential host is correctly detected as a change. |
| 60 | */ |
| 61 | export const gitHubBaseUrlChanged = ( |
| 62 | olds: { baseUrl?: string }, |
| 63 | news: { baseUrl?: string }, |
| 64 | ): Effect.Effect<boolean, AuthError, GitHubCredentials> => |
| 65 | Effect.gen(function* () { |
| 66 | const oldUrl = yield* effectiveGitHubBaseUrl(olds.baseUrl); |
| 67 | const newUrl = yield* effectiveGitHubBaseUrl(news.baseUrl); |
| 68 | return oldUrl !== newUrl; |
| 69 | }); |