@cat-factory/server 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/agents/CompositeAgentExecutor.d.ts +39 -0
- package/dist/agents/CompositeAgentExecutor.d.ts.map +1 -0
- package/dist/agents/CompositeAgentExecutor.js +169 -0
- package/dist/agents/CompositeAgentExecutor.js.map +1 -0
- package/dist/agents/ContainerAgentExecutor.d.ts +235 -0
- package/dist/agents/ContainerAgentExecutor.d.ts.map +1 -0
- package/dist/agents/ContainerAgentExecutor.js +825 -0
- package/dist/agents/ContainerAgentExecutor.js.map +1 -0
- package/dist/agents/ContainerRepoBootstrapper.d.ts +78 -0
- package/dist/agents/ContainerRepoBootstrapper.d.ts.map +1 -0
- package/dist/agents/ContainerRepoBootstrapper.js +279 -0
- package/dist/agents/ContainerRepoBootstrapper.js.map +1 -0
- package/dist/agents/ModelRouter.d.ts +69 -0
- package/dist/agents/ModelRouter.d.ts.map +1 -0
- package/dist/agents/ModelRouter.js +84 -0
- package/dist/agents/ModelRouter.js.map +1 -0
- package/dist/agents/RunnerJobClient.d.ts +41 -0
- package/dist/agents/RunnerJobClient.d.ts.map +1 -0
- package/dist/agents/RunnerJobClient.js +43 -0
- package/dist/agents/RunnerJobClient.js.map +1 -0
- package/dist/agents/modelProviderResolver.d.ts +33 -0
- package/dist/agents/modelProviderResolver.d.ts.map +1 -0
- package/dist/agents/modelProviderResolver.js +48 -0
- package/dist/agents/modelProviderResolver.js.map +1 -0
- package/dist/agents/providerCapabilities.d.ts +22 -0
- package/dist/agents/providerCapabilities.d.ts.map +1 -0
- package/dist/agents/providerCapabilities.js +43 -0
- package/dist/agents/providerCapabilities.js.map +1 -0
- package/dist/agents/resolveRepoTarget.d.ts +33 -0
- package/dist/agents/resolveRepoTarget.d.ts.map +1 -0
- package/dist/agents/resolveRepoTarget.js +81 -0
- package/dist/agents/resolveRepoTarget.js.map +1 -0
- package/dist/app.d.ts +12 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +102 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/GitHubOAuth.d.ts +39 -0
- package/dist/auth/GitHubOAuth.d.ts.map +1 -0
- package/dist/auth/GitHubOAuth.js +90 -0
- package/dist/auth/GitHubOAuth.js.map +1 -0
- package/dist/auth/GoogleOAuth.d.ts +35 -0
- package/dist/auth/GoogleOAuth.d.ts.map +1 -0
- package/dist/auth/GoogleOAuth.js +66 -0
- package/dist/auth/GoogleOAuth.js.map +1 -0
- package/dist/auth/middleware.d.ts +15 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +63 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/signing.d.ts +50 -0
- package/dist/auth/signing.d.ts.map +1 -0
- package/dist/auth/signing.js +96 -0
- package/dist/auth/signing.js.map +1 -0
- package/dist/auth/wsTicket.d.ts +34 -0
- package/dist/auth/wsTicket.d.ts.map +1 -0
- package/dist/auth/wsTicket.js +50 -0
- package/dist/auth/wsTicket.js.map +1 -0
- package/dist/config/types.d.ts +294 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/url-safety.d.ts +8 -0
- package/dist/config/url-safety.d.ts.map +1 -0
- package/dist/config/url-safety.js +11 -0
- package/dist/config/url-safety.js.map +1 -0
- package/dist/containers/ContainerSessionService.d.ts +67 -0
- package/dist/containers/ContainerSessionService.d.ts.map +1 -0
- package/dist/containers/ContainerSessionService.js +44 -0
- package/dist/containers/ContainerSessionService.js.map +1 -0
- package/dist/crypto/WebCryptoPasswordHasher.d.ts +9 -0
- package/dist/crypto/WebCryptoPasswordHasher.d.ts.map +1 -0
- package/dist/crypto/WebCryptoPasswordHasher.js +67 -0
- package/dist/crypto/WebCryptoPasswordHasher.js.map +1 -0
- package/dist/crypto/WebCryptoPersonalSecretCipher.d.ts +6 -0
- package/dist/crypto/WebCryptoPersonalSecretCipher.d.ts.map +1 -0
- package/dist/crypto/WebCryptoPersonalSecretCipher.js +57 -0
- package/dist/crypto/WebCryptoPersonalSecretCipher.js.map +1 -0
- package/dist/crypto/WebCryptoSecretCipher.d.ts +23 -0
- package/dist/crypto/WebCryptoSecretCipher.d.ts.map +1 -0
- package/dist/crypto/WebCryptoSecretCipher.js +60 -0
- package/dist/crypto/WebCryptoSecretCipher.js.map +1 -0
- package/dist/crypto/encoding.d.ts +14 -0
- package/dist/crypto/encoding.d.ts.map +1 -0
- package/dist/crypto/encoding.js +58 -0
- package/dist/crypto/encoding.js.map +1 -0
- package/dist/events/FanOutEventPublisher.d.ts +32 -0
- package/dist/events/FanOutEventPublisher.d.ts.map +1 -0
- package/dist/events/FanOutEventPublisher.js +76 -0
- package/dist/events/FanOutEventPublisher.js.map +1 -0
- package/dist/events/InAppNotificationChannel.d.ts +20 -0
- package/dist/events/InAppNotificationChannel.d.ts.map +1 -0
- package/dist/events/InAppNotificationChannel.js +23 -0
- package/dist/events/InAppNotificationChannel.js.map +1 -0
- package/dist/github/FetchGitHubClient.d.ts +72 -0
- package/dist/github/FetchGitHubClient.d.ts.map +1 -0
- package/dist/github/FetchGitHubClient.js +485 -0
- package/dist/github/FetchGitHubClient.js.map +1 -0
- package/dist/github/FetchGitHubProvisioningClient.d.ts +13 -0
- package/dist/github/FetchGitHubProvisioningClient.d.ts.map +1 -0
- package/dist/github/FetchGitHubProvisioningClient.js +59 -0
- package/dist/github/FetchGitHubProvisioningClient.js.map +1 -0
- package/dist/github/GitHubAppAuth.d.ts +30 -0
- package/dist/github/GitHubAppAuth.d.ts.map +1 -0
- package/dist/github/GitHubAppAuth.js +95 -0
- package/dist/github/GitHubAppAuth.js.map +1 -0
- package/dist/github/GitHubAppRegistry.d.ts +57 -0
- package/dist/github/GitHubAppRegistry.d.ts.map +1 -0
- package/dist/github/GitHubAppRegistry.js +51 -0
- package/dist/github/GitHubAppRegistry.js.map +1 -0
- package/dist/github/GitHubCiStatusProvider.d.ts +21 -0
- package/dist/github/GitHubCiStatusProvider.d.ts.map +1 -0
- package/dist/github/GitHubCiStatusProvider.js +39 -0
- package/dist/github/GitHubCiStatusProvider.js.map +1 -0
- package/dist/github/GitHubMergeabilityProvider.d.ts +26 -0
- package/dist/github/GitHubMergeabilityProvider.d.ts.map +1 -0
- package/dist/github/GitHubMergeabilityProvider.js +38 -0
- package/dist/github/GitHubMergeabilityProvider.js.map +1 -0
- package/dist/github/GitHubPullRequestMerger.d.ts +23 -0
- package/dist/github/GitHubPullRequestMerger.d.ts.map +1 -0
- package/dist/github/GitHubPullRequestMerger.js +38 -0
- package/dist/github/GitHubPullRequestMerger.js.map +1 -0
- package/dist/github/WebCryptoWebhookVerifier.d.ts +9 -0
- package/dist/github/WebCryptoWebhookVerifier.d.ts.map +1 -0
- package/dist/github/WebCryptoWebhookVerifier.js +40 -0
- package/dist/github/WebCryptoWebhookVerifier.js.map +1 -0
- package/dist/github/ensureWorkBranch.d.ts +26 -0
- package/dist/github/ensureWorkBranch.d.ts.map +1 -0
- package/dist/github/ensureWorkBranch.js +97 -0
- package/dist/github/ensureWorkBranch.js.map +1 -0
- package/dist/github/state.d.ts +19 -0
- package/dist/github/state.d.ts.map +1 -0
- package/dist/github/state.js +55 -0
- package/dist/github/state.js.map +1 -0
- package/dist/http/authGate.d.ts +21 -0
- package/dist/http/authGate.d.ts.map +1 -0
- package/dist/http/authGate.js +77 -0
- package/dist/http/authGate.js.map +1 -0
- package/dist/http/cors.d.ts +13 -0
- package/dist/http/cors.d.ts.map +1 -0
- package/dist/http/cors.js +30 -0
- package/dist/http/cors.js.map +1 -0
- package/dist/http/env.d.ts +68 -0
- package/dist/http/env.d.ts.map +1 -0
- package/dist/http/env.js +2 -0
- package/dist/http/env.js.map +1 -0
- package/dist/http/errorHandler.d.ts +4 -0
- package/dist/http/errorHandler.d.ts.map +1 -0
- package/dist/http/errorHandler.js +33 -0
- package/dist/http/errorHandler.js.map +1 -0
- package/dist/http/params.d.ts +8 -0
- package/dist/http/params.d.ts.map +1 -0
- package/dist/http/params.js +13 -0
- package/dist/http/params.js.map +1 -0
- package/dist/http/validation.d.ts +12 -0
- package/dist/http/validation.d.ts.map +1 -0
- package/dist/http/validation.js +21 -0
- package/dist/http/validation.js.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/accounts/AccountController.d.ts +10 -0
- package/dist/modules/accounts/AccountController.d.ts.map +1 -0
- package/dist/modules/accounts/AccountController.js +197 -0
- package/dist/modules/accounts/AccountController.js.map +1 -0
- package/dist/modules/agentRuns/AgentRunController.d.ts +10 -0
- package/dist/modules/agentRuns/AgentRunController.d.ts.map +1 -0
- package/dist/modules/agentRuns/AgentRunController.js +65 -0
- package/dist/modules/agentRuns/AgentRunController.js.map +1 -0
- package/dist/modules/auth/AuthController.d.ts +12 -0
- package/dist/modules/auth/AuthController.d.ts.map +1 -0
- package/dist/modules/auth/AuthController.js +457 -0
- package/dist/modules/auth/AuthController.js.map +1 -0
- package/dist/modules/board/BoardController.d.ts +8 -0
- package/dist/modules/board/BoardController.d.ts.map +1 -0
- package/dist/modules/board/BoardController.js +89 -0
- package/dist/modules/board/BoardController.js.map +1 -0
- package/dist/modules/boardScan/BoardScanController.d.ts +10 -0
- package/dist/modules/boardScan/BoardScanController.d.ts.map +1 -0
- package/dist/modules/boardScan/BoardScanController.js +53 -0
- package/dist/modules/boardScan/BoardScanController.js.map +1 -0
- package/dist/modules/bootstrap/BootstrapController.d.ts +10 -0
- package/dist/modules/bootstrap/BootstrapController.d.ts.map +1 -0
- package/dist/modules/bootstrap/BootstrapController.js +75 -0
- package/dist/modules/bootstrap/BootstrapController.js.map +1 -0
- package/dist/modules/clarity/ClarityReviewController.d.ts +11 -0
- package/dist/modules/clarity/ClarityReviewController.d.ts.map +1 -0
- package/dist/modules/clarity/ClarityReviewController.js +97 -0
- package/dist/modules/clarity/ClarityReviewController.js.map +1 -0
- package/dist/modules/consensus/ConsensusController.d.ts +12 -0
- package/dist/modules/consensus/ConsensusController.d.ts.map +1 -0
- package/dist/modules/consensus/ConsensusController.js +23 -0
- package/dist/modules/consensus/ConsensusController.js.map +1 -0
- package/dist/modules/documents/DocumentSourceController.d.ts +10 -0
- package/dist/modules/documents/DocumentSourceController.d.ts.map +1 -0
- package/dist/modules/documents/DocumentSourceController.js +116 -0
- package/dist/modules/documents/DocumentSourceController.js.map +1 -0
- package/dist/modules/environments/EnvironmentController.d.ts +10 -0
- package/dist/modules/environments/EnvironmentController.d.ts.map +1 -0
- package/dist/modules/environments/EnvironmentController.js +95 -0
- package/dist/modules/environments/EnvironmentController.js.map +1 -0
- package/dist/modules/events/EventsController.d.ts +26 -0
- package/dist/modules/events/EventsController.d.ts.map +1 -0
- package/dist/modules/events/EventsController.js +56 -0
- package/dist/modules/events/EventsController.js.map +1 -0
- package/dist/modules/execution/ExecutionController.d.ts +10 -0
- package/dist/modules/execution/ExecutionController.d.ts.map +1 -0
- package/dist/modules/execution/ExecutionController.js +156 -0
- package/dist/modules/execution/ExecutionController.js.map +1 -0
- package/dist/modules/fragmentLibrary/FragmentLibraryController.d.ts +14 -0
- package/dist/modules/fragmentLibrary/FragmentLibraryController.d.ts.map +1 -0
- package/dist/modules/fragmentLibrary/FragmentLibraryController.js +128 -0
- package/dist/modules/fragmentLibrary/FragmentLibraryController.js.map +1 -0
- package/dist/modules/github/GitHubController.d.ts +12 -0
- package/dist/modules/github/GitHubController.d.ts.map +1 -0
- package/dist/modules/github/GitHubController.js +234 -0
- package/dist/modules/github/GitHubController.js.map +1 -0
- package/dist/modules/github/GitHubWebhookController.d.ts +13 -0
- package/dist/modules/github/GitHubWebhookController.d.ts.map +1 -0
- package/dist/modules/github/GitHubWebhookController.js +74 -0
- package/dist/modules/github/GitHubWebhookController.js.map +1 -0
- package/dist/modules/llmProxy/LlmProxyController.d.ts +18 -0
- package/dist/modules/llmProxy/LlmProxyController.d.ts.map +1 -0
- package/dist/modules/llmProxy/LlmProxyController.js +567 -0
- package/dist/modules/llmProxy/LlmProxyController.js.map +1 -0
- package/dist/modules/localModels/LocalModelEndpointController.d.ts +4 -0
- package/dist/modules/localModels/LocalModelEndpointController.d.ts.map +1 -0
- package/dist/modules/localModels/LocalModelEndpointController.js +58 -0
- package/dist/modules/localModels/LocalModelEndpointController.js.map +1 -0
- package/dist/modules/merge/MergePresetController.d.ts +9 -0
- package/dist/modules/merge/MergePresetController.d.ts.map +1 -0
- package/dist/modules/merge/MergePresetController.js +46 -0
- package/dist/modules/merge/MergePresetController.js.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsController.d.ts +9 -0
- package/dist/modules/modelDefaults/ModelDefaultsController.d.ts.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsController.js +32 -0
- package/dist/modules/modelDefaults/ModelDefaultsController.js.map +1 -0
- package/dist/modules/models/ModelController.d.ts +11 -0
- package/dist/modules/models/ModelController.d.ts.map +1 -0
- package/dist/modules/models/ModelController.js +38 -0
- package/dist/modules/models/ModelController.js.map +1 -0
- package/dist/modules/notifications/NotificationController.d.ts +13 -0
- package/dist/modules/notifications/NotificationController.d.ts.map +1 -0
- package/dist/modules/notifications/NotificationController.js +67 -0
- package/dist/modules/notifications/NotificationController.js.map +1 -0
- package/dist/modules/pipelines/PipelineController.d.ts +5 -0
- package/dist/modules/pipelines/PipelineController.d.ts.map +1 -0
- package/dist/modules/pipelines/PipelineController.js +46 -0
- package/dist/modules/pipelines/PipelineController.js.map +1 -0
- package/dist/modules/promptFragments/PromptFragmentController.d.ts +11 -0
- package/dist/modules/promptFragments/PromptFragmentController.d.ts.map +1 -0
- package/dist/modules/promptFragments/PromptFragmentController.js +18 -0
- package/dist/modules/promptFragments/PromptFragmentController.js.map +1 -0
- package/dist/modules/providers/ApiKeyController.d.ts +13 -0
- package/dist/modules/providers/ApiKeyController.d.ts.map +1 -0
- package/dist/modules/providers/ApiKeyController.js +98 -0
- package/dist/modules/providers/ApiKeyController.js.map +1 -0
- package/dist/modules/providers/PersonalSubscriptionController.d.ts +4 -0
- package/dist/modules/providers/PersonalSubscriptionController.d.ts.map +1 -0
- package/dist/modules/providers/PersonalSubscriptionController.js +48 -0
- package/dist/modules/providers/PersonalSubscriptionController.js.map +1 -0
- package/dist/modules/providers/VendorCredentialController.d.ts +4 -0
- package/dist/modules/providers/VendorCredentialController.d.ts.map +1 -0
- package/dist/modules/providers/VendorCredentialController.js +55 -0
- package/dist/modules/providers/VendorCredentialController.js.map +1 -0
- package/dist/modules/providers/personalCredentialGate.d.ts +34 -0
- package/dist/modules/providers/personalCredentialGate.d.ts.map +1 -0
- package/dist/modules/providers/personalCredentialGate.js +106 -0
- package/dist/modules/providers/personalCredentialGate.js.map +1 -0
- package/dist/modules/recurring/RecurringPipelineController.d.ts +8 -0
- package/dist/modules/recurring/RecurringPipelineController.d.ts.map +1 -0
- package/dist/modules/recurring/RecurringPipelineController.js +58 -0
- package/dist/modules/recurring/RecurringPipelineController.js.map +1 -0
- package/dist/modules/recurring/TrackerSettingsController.d.ts +8 -0
- package/dist/modules/recurring/TrackerSettingsController.d.ts.map +1 -0
- package/dist/modules/recurring/TrackerSettingsController.js +30 -0
- package/dist/modules/recurring/TrackerSettingsController.js.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthController.d.ts +9 -0
- package/dist/modules/releaseHealth/ReleaseHealthController.d.ts.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthController.js +58 -0
- package/dist/modules/releaseHealth/ReleaseHealthController.js.map +1 -0
- package/dist/modules/requirements/RequirementReviewController.d.ts +12 -0
- package/dist/modules/requirements/RequirementReviewController.d.ts.map +1 -0
- package/dist/modules/requirements/RequirementReviewController.js +107 -0
- package/dist/modules/requirements/RequirementReviewController.js.map +1 -0
- package/dist/modules/runners/RunnerPoolController.d.ts +10 -0
- package/dist/modules/runners/RunnerPoolController.d.ts.map +1 -0
- package/dist/modules/runners/RunnerPoolController.js +52 -0
- package/dist/modules/runners/RunnerPoolController.js.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.d.ts +9 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.d.ts.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.js +32 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.js.map +1 -0
- package/dist/modules/services/ServiceMountController.d.ts +11 -0
- package/dist/modules/services/ServiceMountController.d.ts.map +1 -0
- package/dist/modules/services/ServiceMountController.js +64 -0
- package/dist/modules/services/ServiceMountController.js.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsController.d.ts +9 -0
- package/dist/modules/settings/WorkspaceSettingsController.d.ts.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsController.js +32 -0
- package/dist/modules/settings/WorkspaceSettingsController.js.map +1 -0
- package/dist/modules/slack/SlackController.d.ts +17 -0
- package/dist/modules/slack/SlackController.d.ts.map +1 -0
- package/dist/modules/slack/SlackController.js +135 -0
- package/dist/modules/slack/SlackController.js.map +1 -0
- package/dist/modules/tasks/TaskSourceController.d.ts +9 -0
- package/dist/modules/tasks/TaskSourceController.d.ts.map +1 -0
- package/dist/modules/tasks/TaskSourceController.js +103 -0
- package/dist/modules/tasks/TaskSourceController.js.map +1 -0
- package/dist/modules/webSearch/WebSearchProxyController.d.ts +4 -0
- package/dist/modules/webSearch/WebSearchProxyController.d.ts.map +1 -0
- package/dist/modules/webSearch/WebSearchProxyController.js +78 -0
- package/dist/modules/webSearch/WebSearchProxyController.js.map +1 -0
- package/dist/modules/webSearch/upstreams.d.ts +50 -0
- package/dist/modules/webSearch/upstreams.d.ts.map +1 -0
- package/dist/modules/webSearch/upstreams.js +107 -0
- package/dist/modules/webSearch/upstreams.js.map +1 -0
- package/dist/modules/workspaces/WorkspaceController.d.ts +5 -0
- package/dist/modules/workspaces/WorkspaceController.d.ts.map +1 -0
- package/dist/modules/workspaces/WorkspaceController.js +167 -0
- package/dist/modules/workspaces/WorkspaceController.js.map +1 -0
- package/dist/observability/logger.d.ts +9 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +39 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/persistence/mappers.d.ts +101 -0
- package/dist/persistence/mappers.d.ts.map +1 -0
- package/dist/persistence/mappers.js +260 -0
- package/dist/persistence/mappers.js.map +1 -0
- package/dist/runtime/escalateNotifications.d.ts +12 -0
- package/dist/runtime/escalateNotifications.d.ts.map +1 -0
- package/dist/runtime/escalateNotifications.js +25 -0
- package/dist/runtime/escalateNotifications.js.map +1 -0
- package/dist/runtime/gateways.d.ts +159 -0
- package/dist/runtime/gateways.d.ts.map +1 -0
- package/dist/runtime/gateways.js +2 -0
- package/dist/runtime/gateways.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
import {} from '@cat-factory/kernel';
|
|
2
|
+
import { githubProjection as gp } from '@cat-factory/integrations';
|
|
3
|
+
// Thin `fetch`-based GitHubClient: the only place that talks to the GitHub REST
|
|
4
|
+
// API. It authenticates via the App (installation tokens for repo calls, the app
|
|
5
|
+
// JWT for installation-level calls), records a rate-limit snapshot on every
|
|
6
|
+
// response, follows `Link` pagination up to a bounded number of pages, and maps
|
|
7
|
+
// responses to projection entities with the shared pure mappers. Octokit is
|
|
8
|
+
// deliberately avoided — Web Crypto + fetch cover everything we need without the
|
|
9
|
+
// bundle weight (see backend/docs/adr/0001-github-app-integration.md).
|
|
10
|
+
const USER_AGENT = 'cat-factory';
|
|
11
|
+
const API_VERSION = '2022-11-28';
|
|
12
|
+
const ACCEPT = 'application/vnd.github+json';
|
|
13
|
+
const PER_PAGE = 100;
|
|
14
|
+
const MAX_PAGES = 10;
|
|
15
|
+
export class FetchGitHubClient {
|
|
16
|
+
deps;
|
|
17
|
+
constructor(deps) {
|
|
18
|
+
this.deps = deps;
|
|
19
|
+
}
|
|
20
|
+
// ---- installation-level (app JWT) --------------------------------------
|
|
21
|
+
async getInstallation(installationId) {
|
|
22
|
+
// An installation belongs to exactly one App; probe each configured App's JWT
|
|
23
|
+
// until one can see it (404 = not this App's), so the binding records the
|
|
24
|
+
// owning App for later token minting (ADR 0005).
|
|
25
|
+
for (const { appId } of this.deps.registry.apps()) {
|
|
26
|
+
try {
|
|
27
|
+
const { json } = await this.request(`/app/installations/${installationId}`, {
|
|
28
|
+
installationId,
|
|
29
|
+
auth: 'app',
|
|
30
|
+
appId,
|
|
31
|
+
});
|
|
32
|
+
const body = json;
|
|
33
|
+
return {
|
|
34
|
+
accountLogin: body.account?.login ?? '',
|
|
35
|
+
targetType: body.target_type === 'Organization' ? 'Organization' : 'User',
|
|
36
|
+
appId,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (err instanceof GitHubApiError && err.status === 404)
|
|
41
|
+
continue;
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
throw new GitHubApiError(404, `Installation ${installationId} not found on any configured App`);
|
|
46
|
+
}
|
|
47
|
+
async listInstallations() {
|
|
48
|
+
// App-JWT call, so no specific installation: pass 0 (used only for the
|
|
49
|
+
// best-effort rate-limit snapshot). Listed per App and merged, so the connect
|
|
50
|
+
// picker surfaces installations of both the default and privileged Apps.
|
|
51
|
+
const out = [];
|
|
52
|
+
for (const { appId } of this.deps.registry.apps()) {
|
|
53
|
+
const page = await this.paginate(`/app/installations?per_page=${PER_PAGE}`, { installationId: 0, auth: 'app', appId }, (json) => (json ?? []).map((i) => ({
|
|
54
|
+
installationId: i.id,
|
|
55
|
+
accountLogin: i.account?.login ?? '',
|
|
56
|
+
targetType: i.target_type === 'Organization' ? 'Organization' : 'User',
|
|
57
|
+
accountAvatarUrl: i.account?.avatar_url ?? null,
|
|
58
|
+
})));
|
|
59
|
+
out.push(...page);
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
async listInstallationRepos(installationId) {
|
|
64
|
+
const syncedAt = this.deps.clock.now();
|
|
65
|
+
const items = await this.paginate(`/installation/repositories?per_page=${PER_PAGE}`, { installationId }, (json) => {
|
|
66
|
+
const repos = json.repositories ?? [];
|
|
67
|
+
return repos.map((r) => gp.toRepoProjection(r, installationId, syncedAt));
|
|
68
|
+
});
|
|
69
|
+
return { items };
|
|
70
|
+
}
|
|
71
|
+
// ---- reads --------------------------------------------------------------
|
|
72
|
+
async getRepo(installationId, ref) {
|
|
73
|
+
const { json } = await this.request(`/repos/${ref.owner}/${ref.repo}`, { installationId });
|
|
74
|
+
return gp.toRepoProjection(json, installationId, this.deps.clock.now());
|
|
75
|
+
}
|
|
76
|
+
async listBranches(installationId, ref, etag) {
|
|
77
|
+
const syncedAt = this.deps.clock.now();
|
|
78
|
+
const first = await this.request(`/repos/${ref.owner}/${ref.repo}/branches?per_page=${PER_PAGE}`, { installationId, etag });
|
|
79
|
+
if (first.status === 304)
|
|
80
|
+
return { items: [], notModified: true, etag };
|
|
81
|
+
const items = first.json.map((b) => gp.toBranchProjection(b, 0, syncedAt));
|
|
82
|
+
// branches don't carry a repo id; backfill it from the repo we already know.
|
|
83
|
+
const repoId = await this.repoId(installationId, ref);
|
|
84
|
+
return {
|
|
85
|
+
items: items.map((b) => ({ ...b, repoGithubId: repoId })),
|
|
86
|
+
etag: first.etag,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
async listRootEntries(installationId, ref) {
|
|
90
|
+
let json;
|
|
91
|
+
try {
|
|
92
|
+
;
|
|
93
|
+
({ json } = await this.request(`/repos/${ref.owner}/${ref.repo}/contents/`, {
|
|
94
|
+
installationId,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
// An empty repository has no default branch, so the contents endpoint 404s.
|
|
99
|
+
// That's the signal we want — treat it as "no entries", not an error.
|
|
100
|
+
if (err instanceof GitHubApiError && err.status === 404)
|
|
101
|
+
return [];
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
const entries = Array.isArray(json)
|
|
105
|
+
? json
|
|
106
|
+
: [];
|
|
107
|
+
return entries.map((e) => ({ path: e.path ?? e.name ?? '', type: e.type ?? 'file' }));
|
|
108
|
+
}
|
|
109
|
+
async listDirectory(installationId, ref, path, gitRef) {
|
|
110
|
+
const clean = path.replace(/^\/+|\/+$/g, '');
|
|
111
|
+
const query = gitRef ? `?ref=${encodeURIComponent(gitRef)}` : '';
|
|
112
|
+
let json;
|
|
113
|
+
try {
|
|
114
|
+
;
|
|
115
|
+
({ json } = await this.request(`/repos/${ref.owner}/${ref.repo}/contents/${clean}${query}`, {
|
|
116
|
+
installationId,
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
// Missing path / empty repo → no entries (mirrors listRootEntries).
|
|
121
|
+
if (err instanceof GitHubApiError && err.status === 404)
|
|
122
|
+
return [];
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
125
|
+
// A directory returns an array; a single file returns an object — coerce both.
|
|
126
|
+
const arr = Array.isArray(json) ? json : [json];
|
|
127
|
+
return arr.map((e) => ({
|
|
128
|
+
path: e.path ?? e.name ?? '',
|
|
129
|
+
name: e.name ?? (e.path ?? '').split('/').pop() ?? '',
|
|
130
|
+
type: e.type ?? 'file',
|
|
131
|
+
sha: e.sha ?? '',
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
async getFileContent(installationId, ref, path, gitRef) {
|
|
135
|
+
const clean = path.replace(/^\/+/, '');
|
|
136
|
+
const query = gitRef ? `?ref=${encodeURIComponent(gitRef)}` : '';
|
|
137
|
+
let json;
|
|
138
|
+
try {
|
|
139
|
+
;
|
|
140
|
+
({ json } = await this.request(`/repos/${ref.owner}/${ref.repo}/contents/${clean}${query}`, {
|
|
141
|
+
installationId,
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
if (err instanceof GitHubApiError && err.status === 404)
|
|
146
|
+
return null;
|
|
147
|
+
throw err;
|
|
148
|
+
}
|
|
149
|
+
const file = json;
|
|
150
|
+
if (file.type !== 'file' || typeof file.content !== 'string')
|
|
151
|
+
return null;
|
|
152
|
+
const content = file.encoding === 'base64' ? decodeBase64Utf8(file.content) : file.content;
|
|
153
|
+
return { content, sha: file.sha ?? '' };
|
|
154
|
+
}
|
|
155
|
+
async listPullRequests(installationId, ref, opts = {}) {
|
|
156
|
+
const syncedAt = this.deps.clock.now();
|
|
157
|
+
const sinceMs = opts.since ? Date.parse(opts.since) : null;
|
|
158
|
+
const items = await this.paginate(`/repos/${ref.owner}/${ref.repo}/pulls?state=all&sort=updated&direction=desc&per_page=${PER_PAGE}`, { installationId, etag: opts.etag }, (json) => json.map((p) => gp.toPullRequestProjection(p, gp.pullRepoGithubId(p) ?? 0, syncedAt)),
|
|
159
|
+
// Pulls are sorted newest-updated first; stop once we cross `since`.
|
|
160
|
+
(page) => sinceMs !== null && page.length > 0 && (page[page.length - 1].updatedAt ?? 0) < sinceMs);
|
|
161
|
+
const filtered = sinceMs !== null ? items.filter((p) => (p.updatedAt ?? 0) >= sinceMs) : items;
|
|
162
|
+
return { items: filtered };
|
|
163
|
+
}
|
|
164
|
+
async listIssues(installationId, ref, opts = {}) {
|
|
165
|
+
const syncedAt = this.deps.clock.now();
|
|
166
|
+
const repoId = await this.repoId(installationId, ref);
|
|
167
|
+
const since = opts.since ? `&since=${encodeURIComponent(opts.since)}` : '';
|
|
168
|
+
const items = await this.paginate(`/repos/${ref.owner}/${ref.repo}/issues?state=all&sort=updated&per_page=${PER_PAGE}${since}`, { installationId }, (json) => json
|
|
169
|
+
.filter((i) => !gp.isPullRequest(i))
|
|
170
|
+
.map((i) => gp.toIssueProjection(i, repoId, syncedAt)));
|
|
171
|
+
return { items };
|
|
172
|
+
}
|
|
173
|
+
async getIssue(installationId, ref, issueNumber) {
|
|
174
|
+
const base = `/repos/${ref.owner}/${ref.repo}/issues/${issueNumber}`;
|
|
175
|
+
const { json } = await this.request(base, { installationId });
|
|
176
|
+
const issue = (json ?? {});
|
|
177
|
+
// Comments are a separate paginated collection; oldest→newest is the API's
|
|
178
|
+
// default order. One page (100) is plenty of context for an agent.
|
|
179
|
+
const commentsRes = await this.request(`${base}/comments?per_page=${PER_PAGE}`, {
|
|
180
|
+
installationId,
|
|
181
|
+
});
|
|
182
|
+
const rawComments = (commentsRes.json ?? []);
|
|
183
|
+
return {
|
|
184
|
+
number: issue.number ?? issueNumber,
|
|
185
|
+
title: issue.title ?? '(untitled)',
|
|
186
|
+
state: issue.state ?? '',
|
|
187
|
+
url: issue.html_url ?? `https://github.com/${ref.owner}/${ref.repo}/issues/${issueNumber}`,
|
|
188
|
+
author: issue.user?.login ?? null,
|
|
189
|
+
assignee: issue.assignee?.login ?? null,
|
|
190
|
+
labels: (issue.labels ?? [])
|
|
191
|
+
.map((l) => (typeof l === 'string' ? l : (l?.name ?? '')))
|
|
192
|
+
.filter(Boolean),
|
|
193
|
+
body: issue.body ?? '',
|
|
194
|
+
comments: (Array.isArray(rawComments) ? rawComments : []).map((c) => ({
|
|
195
|
+
author: c.user?.login ?? '',
|
|
196
|
+
createdAt: c.created_at ?? '',
|
|
197
|
+
body: c.body ?? '',
|
|
198
|
+
})),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async searchIssues(installationId, query, limit = 20) {
|
|
202
|
+
const q = encodeURIComponent(`${query} is:issue`);
|
|
203
|
+
const per = Math.min(Math.max(limit, 1), 100);
|
|
204
|
+
const { json } = await this.request(`/search/issues?q=${q}&per_page=${per}`, { installationId });
|
|
205
|
+
const items = (json?.items ?? []).filter((i) => !i.pull_request);
|
|
206
|
+
const hits = [];
|
|
207
|
+
for (const item of items) {
|
|
208
|
+
const parts = parseIssueHtmlUrl(item.html_url ?? '');
|
|
209
|
+
if (!parts)
|
|
210
|
+
continue;
|
|
211
|
+
hits.push({
|
|
212
|
+
owner: parts.owner,
|
|
213
|
+
repo: parts.repo,
|
|
214
|
+
number: item.number ?? parts.number,
|
|
215
|
+
title: item.title ?? '(untitled)',
|
|
216
|
+
state: item.state ?? '',
|
|
217
|
+
url: item.html_url ?? '',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return hits.slice(0, limit);
|
|
221
|
+
}
|
|
222
|
+
async searchCode(installationId, query, limit = 20) {
|
|
223
|
+
const per = Math.min(Math.max(limit, 1), 100);
|
|
224
|
+
const { json } = await this.request(`/search/code?q=${encodeURIComponent(query)}&per_page=${per}`, { installationId });
|
|
225
|
+
const items = json?.items ?? [];
|
|
226
|
+
const hits = [];
|
|
227
|
+
for (const item of items) {
|
|
228
|
+
const owner = item.repository?.owner?.login;
|
|
229
|
+
const repo = item.repository?.name;
|
|
230
|
+
const path = item.path;
|
|
231
|
+
if (!owner || !repo || !path)
|
|
232
|
+
continue;
|
|
233
|
+
hits.push({
|
|
234
|
+
owner,
|
|
235
|
+
repo,
|
|
236
|
+
path,
|
|
237
|
+
url: item.html_url ?? `https://github.com/${owner}/${repo}/blob/HEAD/${path}`,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return hits.slice(0, limit);
|
|
241
|
+
}
|
|
242
|
+
async listCommits(installationId, ref, opts = {}) {
|
|
243
|
+
const syncedAt = this.deps.clock.now();
|
|
244
|
+
const repoId = await this.repoId(installationId, ref);
|
|
245
|
+
const since = opts.since ? `&since=${encodeURIComponent(opts.since)}` : '';
|
|
246
|
+
const sha = opts.sha ? `&sha=${encodeURIComponent(opts.sha)}` : '';
|
|
247
|
+
const items = await this.paginate(`/repos/${ref.owner}/${ref.repo}/commits?per_page=${PER_PAGE}${since}${sha}`, { installationId }, (json) => json.map((c) => gp.toCommitProjection(c, repoId, syncedAt)));
|
|
248
|
+
return { items };
|
|
249
|
+
}
|
|
250
|
+
async listCheckRuns(installationId, ref, sha) {
|
|
251
|
+
const syncedAt = this.deps.clock.now();
|
|
252
|
+
const repoId = await this.repoId(installationId, ref);
|
|
253
|
+
const { json } = await this.request(`/repos/${ref.owner}/${ref.repo}/commits/${sha}/check-runs?per_page=${PER_PAGE}`, { installationId });
|
|
254
|
+
const runs = json.check_runs ?? [];
|
|
255
|
+
return { items: runs.map((r) => gp.toCheckRunProjection(r, repoId, syncedAt)) };
|
|
256
|
+
}
|
|
257
|
+
// ---- writes -------------------------------------------------------------
|
|
258
|
+
async createBranch(installationId, ref, name, fromSha) {
|
|
259
|
+
await this.request(`/repos/${ref.owner}/${ref.repo}/git/refs`, {
|
|
260
|
+
installationId,
|
|
261
|
+
method: 'POST',
|
|
262
|
+
body: { ref: `refs/heads/${name}`, sha: fromSha },
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
async commitFiles(installationId, ref, input) {
|
|
266
|
+
const base = `/repos/${ref.owner}/${ref.repo}/git`;
|
|
267
|
+
// 1. Resolve the branch tip (the parent commit) and its tree.
|
|
268
|
+
const baseSha = input.baseSha ??
|
|
269
|
+
(await this.request(`${base}/ref/heads/${input.branch}`, { installationId })).json.object?.sha;
|
|
270
|
+
if (!baseSha)
|
|
271
|
+
throw new Error(`Cannot resolve base commit for branch ${input.branch}`);
|
|
272
|
+
const baseCommit = (await this.request(`${base}/commits/${baseSha}`, { installationId }))
|
|
273
|
+
.json;
|
|
274
|
+
const baseTreeSha = baseCommit.tree?.sha;
|
|
275
|
+
// 2. Create a blob per file, then a tree referencing them.
|
|
276
|
+
const tree = await Promise.all(input.files.map(async (file) => {
|
|
277
|
+
const blob = (await this.request(`${base}/blobs`, {
|
|
278
|
+
installationId,
|
|
279
|
+
method: 'POST',
|
|
280
|
+
body: { content: file.content, encoding: 'utf-8' },
|
|
281
|
+
})).json;
|
|
282
|
+
return { path: file.path, mode: '100644', type: 'blob', sha: blob.sha };
|
|
283
|
+
}));
|
|
284
|
+
const newTree = (await this.request(`${base}/trees`, {
|
|
285
|
+
installationId,
|
|
286
|
+
method: 'POST',
|
|
287
|
+
body: { base_tree: baseTreeSha, tree },
|
|
288
|
+
})).json;
|
|
289
|
+
// 3. Create the commit and fast-forward the branch ref to it.
|
|
290
|
+
const commit = (await this.request(`${base}/commits`, {
|
|
291
|
+
installationId,
|
|
292
|
+
method: 'POST',
|
|
293
|
+
body: { message: input.message, tree: newTree.sha, parents: [baseSha] },
|
|
294
|
+
})).json;
|
|
295
|
+
await this.request(`${base}/refs/heads/${input.branch}`, {
|
|
296
|
+
installationId,
|
|
297
|
+
method: 'PATCH',
|
|
298
|
+
body: { sha: commit.sha },
|
|
299
|
+
});
|
|
300
|
+
return { sha: commit.sha };
|
|
301
|
+
}
|
|
302
|
+
async openPullRequest(installationId, ref, input) {
|
|
303
|
+
const { json } = await this.request(`/repos/${ref.owner}/${ref.repo}/pulls`, {
|
|
304
|
+
installationId,
|
|
305
|
+
method: 'POST',
|
|
306
|
+
body: input,
|
|
307
|
+
});
|
|
308
|
+
const p = json;
|
|
309
|
+
return gp.toPullRequestProjection(p, gp.pullRepoGithubId(p) ?? 0, this.deps.clock.now());
|
|
310
|
+
}
|
|
311
|
+
async createIssue(installationId, ref, input) {
|
|
312
|
+
const { json } = await this.request(`/repos/${ref.owner}/${ref.repo}/issues`, {
|
|
313
|
+
installationId,
|
|
314
|
+
method: 'POST',
|
|
315
|
+
body: { title: input.title, body: input.body },
|
|
316
|
+
});
|
|
317
|
+
const issue = (json ?? {});
|
|
318
|
+
return { number: issue.number ?? 0, url: issue.html_url ?? '' };
|
|
319
|
+
}
|
|
320
|
+
async updatePullRequest(installationId, ref, number, patch) {
|
|
321
|
+
const { json } = await this.request(`/repos/${ref.owner}/${ref.repo}/pulls/${number}`, {
|
|
322
|
+
installationId,
|
|
323
|
+
method: 'PATCH',
|
|
324
|
+
body: patch,
|
|
325
|
+
});
|
|
326
|
+
const p = json;
|
|
327
|
+
return gp.toPullRequestProjection(p, gp.pullRepoGithubId(p) ?? 0, this.deps.clock.now());
|
|
328
|
+
}
|
|
329
|
+
async getPullRequestMergeability(installationId, ref, number) {
|
|
330
|
+
const { json } = await this.request(`/repos/${ref.owner}/${ref.repo}/pulls/${number}`, {
|
|
331
|
+
installationId,
|
|
332
|
+
});
|
|
333
|
+
const p = (json ?? {});
|
|
334
|
+
return {
|
|
335
|
+
mergeable: typeof p.mergeable === 'boolean' ? p.mergeable : null,
|
|
336
|
+
mergeableState: typeof p.mergeable_state === 'string' ? p.mergeable_state : 'unknown',
|
|
337
|
+
headSha: p.head?.sha ?? null,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
async mergePullRequest(installationId, ref, number, input) {
|
|
341
|
+
await this.request(`/repos/${ref.owner}/${ref.repo}/pulls/${number}/merge`, {
|
|
342
|
+
installationId,
|
|
343
|
+
method: 'PUT',
|
|
344
|
+
body: { merge_method: input?.method ?? 'merge' },
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
async deleteBranch(installationId, ref, branch) {
|
|
348
|
+
try {
|
|
349
|
+
await this.request(`/repos/${ref.owner}/${ref.repo}/git/refs/heads/${encodeURIComponent(branch)}`, { installationId, method: 'DELETE' });
|
|
350
|
+
}
|
|
351
|
+
catch (err) {
|
|
352
|
+
// 404/422 mean the ref is already gone (or never existed) — treat as success so
|
|
353
|
+
// deletion is idempotent for a caller that may retry or race a manual delete.
|
|
354
|
+
if (err instanceof GitHubApiError && (err.status === 404 || err.status === 422))
|
|
355
|
+
return;
|
|
356
|
+
throw err;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
async comment(installationId, ref, issueOrPrNumber, body) {
|
|
360
|
+
await this.request(`/repos/${ref.owner}/${ref.repo}/issues/${issueOrPrNumber}/comments`, {
|
|
361
|
+
installationId,
|
|
362
|
+
method: 'POST',
|
|
363
|
+
body: { body },
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
// ---- internals ----------------------------------------------------------
|
|
367
|
+
/** Lazily resolve a repo's numeric id (needed where the payload omits it). */
|
|
368
|
+
async repoId(installationId, ref) {
|
|
369
|
+
const { json } = await this.request(`/repos/${ref.owner}/${ref.repo}`, { installationId });
|
|
370
|
+
return json.id ?? 0;
|
|
371
|
+
}
|
|
372
|
+
/** Follow `Link` pagination, mapping each page, until exhausted/capped/`stop`. */
|
|
373
|
+
async paginate(path, opts, map, stop) {
|
|
374
|
+
const all = [];
|
|
375
|
+
let url = path;
|
|
376
|
+
for (let page = 0; url && page < MAX_PAGES; page++) {
|
|
377
|
+
const response = await this.request(url, opts);
|
|
378
|
+
if (response.status === 304)
|
|
379
|
+
break;
|
|
380
|
+
const mapped = map(response.json);
|
|
381
|
+
all.push(...mapped);
|
|
382
|
+
if (stop?.(mapped))
|
|
383
|
+
break;
|
|
384
|
+
url = response.next;
|
|
385
|
+
}
|
|
386
|
+
return all;
|
|
387
|
+
}
|
|
388
|
+
async request(pathOrUrl, opts) {
|
|
389
|
+
const url = pathOrUrl.startsWith('http') ? pathOrUrl : `${this.deps.apiBase}${pathOrUrl}`;
|
|
390
|
+
const token = opts.auth === 'app'
|
|
391
|
+
? await this.deps.registry
|
|
392
|
+
.authForApp(opts.appId ?? this.deps.registry.defaultAppId)
|
|
393
|
+
.appJwt()
|
|
394
|
+
: await this.deps.registry.installationToken(opts.installationId);
|
|
395
|
+
const headers = {
|
|
396
|
+
authorization: `Bearer ${token}`,
|
|
397
|
+
accept: ACCEPT,
|
|
398
|
+
'user-agent': USER_AGENT,
|
|
399
|
+
'x-github-api-version': API_VERSION,
|
|
400
|
+
};
|
|
401
|
+
if (opts.etag)
|
|
402
|
+
headers['if-none-match'] = opts.etag;
|
|
403
|
+
if (opts.body !== undefined)
|
|
404
|
+
headers['content-type'] = 'application/json';
|
|
405
|
+
const res = await fetch(url, {
|
|
406
|
+
method: opts.method ?? 'GET',
|
|
407
|
+
headers,
|
|
408
|
+
body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,
|
|
409
|
+
});
|
|
410
|
+
await this.recordRateLimit(opts.installationId, res);
|
|
411
|
+
if (res.status === 304)
|
|
412
|
+
return { status: 304, res, json: null, next: undefined };
|
|
413
|
+
if (!res.ok) {
|
|
414
|
+
const text = await res.text().catch(() => '');
|
|
415
|
+
throw new GitHubApiError(res.status, `GitHub ${opts.method ?? 'GET'} ${url} → ${res.status}: ${text.slice(0, 300)}`);
|
|
416
|
+
}
|
|
417
|
+
const json = res.status === 204 ? null : await res.json().catch(() => null);
|
|
418
|
+
return {
|
|
419
|
+
status: res.status,
|
|
420
|
+
res,
|
|
421
|
+
json,
|
|
422
|
+
etag: res.headers.get('etag') ?? undefined,
|
|
423
|
+
next: parseNextLink(res.headers.get('link')),
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
async recordRateLimit(installationId, res) {
|
|
427
|
+
const limit = numHeader(res, 'x-ratelimit-limit');
|
|
428
|
+
const remaining = numHeader(res, 'x-ratelimit-remaining');
|
|
429
|
+
const resetSec = numHeader(res, 'x-ratelimit-reset');
|
|
430
|
+
if (limit === null && remaining === null)
|
|
431
|
+
return;
|
|
432
|
+
const snapshot = {
|
|
433
|
+
installationId,
|
|
434
|
+
resource: res.headers.get('x-ratelimit-resource') ?? 'core',
|
|
435
|
+
limit,
|
|
436
|
+
remaining,
|
|
437
|
+
resetAt: resetSec === null ? null : resetSec * 1000,
|
|
438
|
+
observedAt: this.deps.clock.now(),
|
|
439
|
+
};
|
|
440
|
+
// Best-effort: rate-limit accounting must never fail the actual call.
|
|
441
|
+
await this.deps.rateLimitRepository.record(snapshot).catch(() => { });
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/** Carries the HTTP status so callers/queue can decide whether to retry. */
|
|
445
|
+
export class GitHubApiError extends Error {
|
|
446
|
+
status;
|
|
447
|
+
constructor(status, message) {
|
|
448
|
+
super(message);
|
|
449
|
+
this.status = status;
|
|
450
|
+
this.name = 'GitHubApiError';
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/** Derive `{owner, repo, number}` from an issue's `html_url`, or null if it doesn't match. */
|
|
454
|
+
function parseIssueHtmlUrl(url) {
|
|
455
|
+
const m = url.match(/github\.com\/([^/]+)\/([^/]+)\/issues\/(\d+)/);
|
|
456
|
+
if (!m)
|
|
457
|
+
return null;
|
|
458
|
+
return { owner: m[1], repo: m[2], number: Number(m[3]) };
|
|
459
|
+
}
|
|
460
|
+
/** Decode the contents API's base64 (whitespace-laden) payload to a UTF-8 string. */
|
|
461
|
+
function decodeBase64Utf8(value) {
|
|
462
|
+
const binary = atob(value.replace(/\s+/g, ''));
|
|
463
|
+
const bytes = new Uint8Array(binary.length);
|
|
464
|
+
for (let i = 0; i < binary.length; i++)
|
|
465
|
+
bytes[i] = binary.charCodeAt(i);
|
|
466
|
+
return new TextDecoder().decode(bytes);
|
|
467
|
+
}
|
|
468
|
+
function numHeader(res, name) {
|
|
469
|
+
const raw = res.headers.get(name);
|
|
470
|
+
if (raw === null)
|
|
471
|
+
return null;
|
|
472
|
+
const n = Number(raw);
|
|
473
|
+
return Number.isFinite(n) ? n : null;
|
|
474
|
+
}
|
|
475
|
+
function parseNextLink(link) {
|
|
476
|
+
if (!link)
|
|
477
|
+
return undefined;
|
|
478
|
+
for (const part of link.split(',')) {
|
|
479
|
+
const match = part.match(/<([^>]+)>\s*;\s*rel="next"/);
|
|
480
|
+
if (match)
|
|
481
|
+
return match[1];
|
|
482
|
+
}
|
|
483
|
+
return undefined;
|
|
484
|
+
}
|
|
485
|
+
//# sourceMappingURL=FetchGitHubClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FetchGitHubClient.js","sourceRoot":"","sources":["../../src/github/FetchGitHubClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CreateRepoInput, GitHubProvisioningClient, InstallationPermissions, ProvisionedRepo } from '@cat-factory/kernel';
|
|
2
|
+
import type { GitHubAppRegistry } from './GitHubAppRegistry.js';
|
|
3
|
+
export interface FetchGitHubProvisioningClientDependencies {
|
|
4
|
+
registry: GitHubAppRegistry;
|
|
5
|
+
apiBase: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class FetchGitHubProvisioningClient implements GitHubProvisioningClient {
|
|
8
|
+
private readonly deps;
|
|
9
|
+
constructor(deps: FetchGitHubProvisioningClientDependencies);
|
|
10
|
+
getGrantedPermissions(installationId: number): Promise<InstallationPermissions>;
|
|
11
|
+
createRepoInOrg(installationId: number, input: CreateRepoInput): Promise<ProvisionedRepo>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=FetchGitHubProvisioningClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FetchGitHubProvisioningClient.d.ts","sourceRoot":"","sources":["../../src/github/FetchGitHubProvisioningClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAa/D,MAAM,WAAW,yCAAyC;IACxD,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAA;CAChB;AAoBD,qBAAa,6BAA8B,YAAW,wBAAwB;IAChE,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,yCAAyC,EAAI;IAEhF,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAE9E;IAEK,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAoC9F;CACF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// `fetch`-based adapter for the privileged provisioning slice (ADR 0005). Routes
|
|
2
|
+
// token minting through the registry, so it acts as whichever App owns the
|
|
3
|
+
// installation passed in — for a privileged-tier org that's the privileged App
|
|
4
|
+
// carrying `Administration: write`. Mirrors `FetchGitHubClient`'s
|
|
5
|
+
// Web-Crypto/`fetch`-only approach (no Octokit; see ADR 0001). Runtime-neutral and
|
|
6
|
+
// shared by every facade so a deployment can provision repos regardless of runtime.
|
|
7
|
+
const USER_AGENT = 'cat-factory';
|
|
8
|
+
const API_VERSION = '2022-11-28';
|
|
9
|
+
const ACCEPT = 'application/vnd.github+json';
|
|
10
|
+
/** An HTTP error that carries its status so the core can branch (403 / 422 → delegate). */
|
|
11
|
+
class GitHubHttpError extends Error {
|
|
12
|
+
status;
|
|
13
|
+
constructor(status, message) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.status = status;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class FetchGitHubProvisioningClient {
|
|
19
|
+
deps;
|
|
20
|
+
constructor(deps) {
|
|
21
|
+
this.deps = deps;
|
|
22
|
+
}
|
|
23
|
+
getGrantedPermissions(installationId) {
|
|
24
|
+
return this.deps.registry.installationPermissions(installationId);
|
|
25
|
+
}
|
|
26
|
+
async createRepoInOrg(installationId, input) {
|
|
27
|
+
const token = await this.deps.registry.installationToken(installationId);
|
|
28
|
+
const res = await fetch(`${this.deps.apiBase}/orgs/${encodeURIComponent(input.org)}/repos`, {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
headers: {
|
|
31
|
+
authorization: `Bearer ${token}`,
|
|
32
|
+
accept: ACCEPT,
|
|
33
|
+
'user-agent': USER_AGENT,
|
|
34
|
+
'x-github-api-version': API_VERSION,
|
|
35
|
+
'content-type': 'application/json',
|
|
36
|
+
},
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
name: input.name,
|
|
39
|
+
private: input.private ?? true,
|
|
40
|
+
description: input.description,
|
|
41
|
+
auto_init: input.autoInit ?? false,
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
// Status-carrying errors so the core delegates on 403 (org policy) / 422
|
|
45
|
+
// (name already exists) and surfaces anything else as a hard failure.
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
throw new GitHubHttpError(res.status, `Failed to create repo ${input.org}/${input.name} (HTTP ${res.status})`);
|
|
48
|
+
}
|
|
49
|
+
const body = (await res.json());
|
|
50
|
+
return {
|
|
51
|
+
githubId: body.id,
|
|
52
|
+
owner: body.owner.login,
|
|
53
|
+
name: body.name,
|
|
54
|
+
defaultBranch: body.default_branch,
|
|
55
|
+
private: body.private,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=FetchGitHubProvisioningClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FetchGitHubProvisioningClient.js","sourceRoot":"","sources":["../../src/github/FetchGitHubProvisioningClient.ts"],"names":[],"mappings":"AAQA,iFAAiF;AACjF,2EAA2E;AAC3E,+EAA+E;AAC/E,kEAAkE;AAClE,mFAAmF;AACnF,oFAAoF;AAEpF,MAAM,UAAU,GAAG,aAAa,CAAA;AAChC,MAAM,WAAW,GAAG,YAAY,CAAA;AAChC,MAAM,MAAM,GAAG,6BAA6B,CAAA;AAO5C,2FAA2F;AAC3F,MAAM,eAAgB,SAAQ,KAAK;IAEtB,MAAM;IADjB,YACW,MAAc,EACvB,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAA;sBAHL,MAAM;IAIjB,CAAC;CACF;AAUD,MAAM,OAAO,6BAA6B;IACX,IAAI;IAAjC,YAA6B,IAA+C;oBAA/C,IAAI;IAA8C,CAAC;IAEhF,qBAAqB,CAAC,cAAsB;QAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC,cAAc,CAAC,CAAA;IACnE,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,cAAsB,EAAE,KAAsB;QAClE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAA;QACxE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,SAAS,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE;YAC1F,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,YAAY,EAAE,UAAU;gBACxB,sBAAsB,EAAE,WAAW;gBACnC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;gBAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,SAAS,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK;aACnC,CAAC;SACH,CAAC,CAAA;QAEF,yEAAyE;QACzE,sEAAsE;QACtE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,eAAe,CACvB,GAAG,CAAC,MAAM,EACV,yBAAyB,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,IAAI,UAAU,GAAG,CAAC,MAAM,GAAG,CACxE,CAAA;QACH,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAA;QACtD,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,EAAE;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,aAAa,EAAE,IAAI,CAAC,cAAc;YAClC,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Clock, GitHubInstallationRepository, InstallationPermissions } from '@cat-factory/kernel';
|
|
2
|
+
export interface GitHubAppAuthDependencies {
|
|
3
|
+
appId: string;
|
|
4
|
+
/** App private key in PKCS#8 PEM (`-----BEGIN PRIVATE KEY-----`). */
|
|
5
|
+
privateKeyPem: string;
|
|
6
|
+
installationRepository: GitHubInstallationRepository;
|
|
7
|
+
clock: Clock;
|
|
8
|
+
apiBase: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class GitHubAppAuth {
|
|
11
|
+
private readonly deps;
|
|
12
|
+
private keyPromise?;
|
|
13
|
+
constructor(deps: GitHubAppAuthDependencies);
|
|
14
|
+
/** A short-lived RS256 JWT authenticating as the App. */
|
|
15
|
+
appJwt(): Promise<string>;
|
|
16
|
+
/** A valid installation access token, minting + caching one if needed. */
|
|
17
|
+
installationToken(installationId: number): Promise<string>;
|
|
18
|
+
/**
|
|
19
|
+
* The permissions the installation token actually carries (App ∩ what the
|
|
20
|
+
* install approved) — the source of truth for capability checks. Comes free
|
|
21
|
+
* with the mint response and is cached alongside the token, so a warm process
|
|
22
|
+
* answers without a network call. Used by the provisioner to guard privileged
|
|
23
|
+
* actions (e.g. repo creation) before attempting them.
|
|
24
|
+
*/
|
|
25
|
+
installationPermissions(installationId: number): Promise<InstallationPermissions>;
|
|
26
|
+
private cachedToken;
|
|
27
|
+
private mintInstallationToken;
|
|
28
|
+
private importKey;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=GitHubAppAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitHubAppAuth.d.ts","sourceRoot":"","sources":["../../src/github/GitHubAppAuth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,4BAA4B,EAC5B,uBAAuB,EACxB,MAAM,qBAAqB,CAAA;AAgC5B,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAA;IACrB,sBAAsB,EAAE,4BAA4B,CAAA;IACpD,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AASD,qBAAa,aAAa;IAGZ,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,OAAO,CAAC,UAAU,CAAC,CAAoB;IAEvC,YAA6B,IAAI,EAAE,yBAAyB,EAAI;IAEhE,yDAAyD;IACnD,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAa9B;IAED,0EAA0E;IACpE,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE/D;IAED;;;;;;OAMG;IACG,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAEtF;YAEa,WAAW;YAUX,qBAAqB;IAiCnC,OAAO,CAAC,SAAS;CAYlB"}
|