@happyvertical/repos 0.83.0 → 0.85.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/errors.ts","../src/factory.ts","../src/github/rest.ts","../src/github/index.ts","../src/parsing.ts"],"sourcesContent":["/**\n * Repository error handling\n */\n\nexport enum RepositoryErrorCode {\n NOT_FOUND = 'NOT_FOUND',\n UNAUTHORIZED = 'UNAUTHORIZED',\n FORBIDDEN = 'FORBIDDEN',\n RATE_LIMITED = 'RATE_LIMITED',\n VALIDATION_ERROR = 'VALIDATION_ERROR',\n NETWORK_ERROR = 'NETWORK_ERROR',\n UNKNOWN = 'UNKNOWN',\n}\n\nexport class RepositoryError extends Error {\n constructor(\n message: string,\n public code: RepositoryErrorCode,\n public statusCode?: number,\n public response?: unknown,\n ) {\n super(message);\n this.name = 'RepositoryError';\n Error.captureStackTrace(this, this.constructor);\n }\n\n static fromHTTPStatus(\n statusCode: number,\n message: string,\n response?: unknown,\n ): RepositoryError {\n let code: RepositoryErrorCode;\n\n switch (statusCode) {\n case 404:\n code = RepositoryErrorCode.NOT_FOUND;\n break;\n case 401:\n code = RepositoryErrorCode.UNAUTHORIZED;\n break;\n case 403:\n code = RepositoryErrorCode.FORBIDDEN;\n break;\n case 429:\n code = RepositoryErrorCode.RATE_LIMITED;\n break;\n case 422:\n code = RepositoryErrorCode.VALIDATION_ERROR;\n break;\n default:\n code = RepositoryErrorCode.UNKNOWN;\n }\n\n return new RepositoryError(message, code, statusCode, response);\n }\n\n static networkError(message: string, cause?: Error): RepositoryError {\n return new RepositoryError(\n message,\n RepositoryErrorCode.NETWORK_ERROR,\n undefined,\n cause,\n );\n }\n\n isRetryable(): boolean {\n return (\n this.code === RepositoryErrorCode.RATE_LIMITED ||\n this.code === RepositoryErrorCode.NETWORK_ERROR\n );\n }\n}\n","/**\n * Repository factory function\n *\n * Creates repository instances following the pattern from @happyvertical/files and @happyvertical/sql\n */\n\nimport { RepositoryError, RepositoryErrorCode } from './errors.js';\nimport type { IRepository, RepositoryConfig } from './types.js';\n\n/**\n * Check if value is already a repository instance\n */\nfunction isRepositoryInstance(value: unknown): value is IRepository {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'getIssue' in value &&\n 'createIssue' in value &&\n 'addLabels' in value &&\n typeof (value as IRepository).getIssue === 'function'\n );\n}\n\n/**\n * Get a repository client instance\n *\n * This is the main entry point following the pattern from @happyvertical/files and @happyvertical/sql.\n * It can accept either a configuration object or an existing repository instance.\n *\n * @param options - Repository configuration or existing repository instance\n * @returns Promise resolving to repository interface\n *\n * @example\n * ```typescript\n * import { getRepository } from '@happyvertical/repos';\n *\n * // Create a GitHub repository client\n * const repo = await getRepository({\n * type: 'github',\n * owner: 'happyvertical',\n * repo: 'sdk',\n * token: process.env.GITHUB_TOKEN\n * });\n *\n * // Use the client\n * const issue = await repo.getIssue(352);\n * await repo.addLabels(352, ['type: feature', 'priority: high']);\n *\n * // Pass existing instance (returns it unchanged)\n * const sameRepo = await getRepository(repo);\n * ```\n */\nexport async function getRepository(\n options: RepositoryConfig | IRepository,\n): Promise<IRepository> {\n // If already a repository instance, return it\n if (isRepositoryInstance(options)) {\n return options;\n }\n\n // Validate configuration\n if (!options.type) {\n throw new RepositoryError(\n 'Repository type is required',\n RepositoryErrorCode.VALIDATION_ERROR,\n );\n }\n\n if (!options.owner || !options.repo) {\n throw new RepositoryError(\n 'Repository owner and repo are required',\n RepositoryErrorCode.VALIDATION_ERROR,\n );\n }\n\n if (!options.token) {\n throw new RepositoryError(\n 'Authentication token is required',\n RepositoryErrorCode.UNAUTHORIZED,\n );\n }\n\n // Create repository instance based on type\n switch (options.type) {\n case 'github': {\n const { GitHubRepository } = await import('./github/index.js');\n return new GitHubRepository(options);\n }\n\n case 'gitlab':\n throw new RepositoryError(\n 'GitLab support not yet implemented',\n RepositoryErrorCode.UNKNOWN,\n );\n\n case 'bitbucket':\n throw new RepositoryError(\n 'Bitbucket support not yet implemented',\n RepositoryErrorCode.UNKNOWN,\n );\n\n case 'azure':\n throw new RepositoryError(\n 'Azure DevOps support not yet implemented',\n RepositoryErrorCode.UNKNOWN,\n );\n\n default:\n throw new RepositoryError(\n `Unsupported repository type: ${options.type}`,\n RepositoryErrorCode.VALIDATION_ERROR,\n );\n }\n}\n","/**\n * GitHub REST API client\n */\n\nimport { RepositoryError } from '../errors.js';\n\nexport interface GitHubRestConfig {\n token: string;\n baseUrl?: string;\n}\n\n/**\n * GitHub REST API client\n */\nexport class GitHubRest {\n private token: string;\n private baseUrl: string;\n\n constructor(config: GitHubRestConfig) {\n this.token = config.token;\n this.baseUrl = config.baseUrl || 'https://api.github.com';\n }\n\n /**\n * Make a REST API request\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<unknown> {\n const url = `${this.baseUrl}${path}`;\n const headers = {\n Authorization: `Bearer ${this.token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'Content-Type': 'application/json',\n };\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw RepositoryError.fromHTTPStatus(\n response.status,\n `GitHub API error: ${response.statusText}\\n${error}`,\n error,\n );\n }\n\n return response.json();\n }\n\n /**\n * GET request\n */\n async get(path: string): Promise<unknown> {\n return this.request('GET', path);\n }\n\n /**\n * POST request\n */\n async post(path: string, body: unknown): Promise<unknown> {\n return this.request('POST', path, body);\n }\n\n /**\n * PATCH request\n */\n async patch(path: string, body: unknown): Promise<unknown> {\n return this.request('PATCH', path, body);\n }\n\n /**\n * PUT request\n */\n async put(path: string, body?: unknown): Promise<unknown> {\n return this.request('PUT', path, body);\n }\n\n /**\n * DELETE request\n */\n async delete(path: string): Promise<void> {\n await this.request('DELETE', path);\n }\n}\n","/**\n * GitHub repository implementation\n */\n\nimport { GraphQLClient, type IGraphQLClient } from '@happyvertical/graphql';\nimport type {\n Branch,\n Comment,\n CreateFromTemplateOptions,\n CreateIssueInput,\n CreatePRInput,\n IRepository,\n Issue,\n Label,\n MergeMethod,\n PullRequest,\n Repository,\n RepositoryConfig,\n SearchFilters,\n UpdateIssueInput,\n} from '../types.js';\nimport { GitHubRest } from './rest.js';\n\n/**\n * GitHub repository implementation\n */\nexport class GitHubRepository implements IRepository {\n private rest: GitHubRest;\n private graphql: IGraphQLClient;\n private owner: string;\n private repo: string;\n\n constructor(config: RepositoryConfig) {\n if (config.type !== 'github') {\n throw new Error('Invalid config type for GitHubRepository');\n }\n\n this.owner = config.owner;\n this.repo = config.repo;\n this.rest = new GitHubRest({\n token: config.token,\n baseUrl: config.baseUrl,\n });\n this.graphql = new GraphQLClient({\n endpoint: config.baseUrl\n ? `${config.baseUrl}/graphql`\n : 'https://api.github.com/graphql',\n token: config.token,\n });\n }\n\n // Repository Info\n async getRepository(): Promise<Repository> {\n const data = (await this.rest.get(`/repos/${this.owner}/${this.repo}`)) as {\n name: string;\n owner: { login: string };\n description: string;\n default_branch: string;\n html_url: string;\n private: boolean;\n };\n\n return {\n owner: data.owner.login,\n name: data.name,\n description: data.description,\n defaultBranch: data.default_branch,\n url: data.html_url,\n isPrivate: data.private,\n };\n }\n\n // Issues\n async getIssue(number: number): Promise<Issue> {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/issues/${number}`,\n )) as {\n number: number;\n node_id: string;\n title: string;\n body: string | null;\n state: string;\n labels: Array<{ name: string; color: string; description: string }>;\n assignees: Array<{ login: string; id: number; type: string }>;\n user: { login: string; id: number; type: string };\n created_at: string;\n updated_at: string;\n closed_at: string | null;\n html_url: string;\n comments: number;\n };\n\n return {\n number: data.number,\n id: data.node_id,\n title: data.title,\n body: data.body || '',\n state: data.state === 'open' ? 'open' : 'closed',\n labels: data.labels.map((l) => ({\n name: l.name,\n color: l.color,\n description: l.description,\n })),\n assignees: data.assignees.map((a) => ({\n login: a.login,\n id: String(a.id),\n type: a.type === 'Bot' ? 'Bot' : 'User',\n })),\n author: {\n login: data.user.login,\n id: String(data.user.id),\n type: data.user.type === 'Bot' ? 'Bot' : 'User',\n },\n createdAt: new Date(data.created_at),\n updatedAt: new Date(data.updated_at),\n closedAt: data.closed_at ? new Date(data.closed_at) : undefined,\n url: data.html_url,\n commentsCount: data.comments,\n };\n }\n\n async createIssue(data: CreateIssueInput): Promise<Issue> {\n const result = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/issues`,\n data,\n )) as ReturnType<typeof this.getIssue> extends Promise<infer T> ? T : never;\n return this.getIssue(result.number);\n }\n\n async updateIssue(number: number, data: UpdateIssueInput): Promise<Issue> {\n await this.rest.patch(\n `/repos/${this.owner}/${this.repo}/issues/${number}`,\n data,\n );\n return this.getIssue(number);\n }\n\n async closeIssue(number: number): Promise<void> {\n await this.updateIssue(number, { state: 'closed' });\n }\n\n // Labels\n async addLabels(issueNumber: number, labels: string[]): Promise<void> {\n await this.rest.post(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/labels`,\n { labels },\n );\n }\n\n async removeLabel(issueNumber: number, label: string): Promise<void> {\n const encodedLabel = encodeURIComponent(label);\n await this.rest.delete(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/labels/${encodedLabel}`,\n );\n }\n\n async createLabel(label: Label): Promise<void> {\n await this.rest.post(`/repos/${this.owner}/${this.repo}/labels`, label);\n }\n\n async updateLabel(name: string, label: Label): Promise<void> {\n await this.rest.patch(\n `/repos/${this.owner}/${this.repo}/labels/${encodeURIComponent(name)}`,\n label,\n );\n }\n\n async listLabels(): Promise<Label[]> {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/labels`,\n )) as Array<{ name: string; color: string; description: string }>;\n\n return data.map((l) => ({\n name: l.name,\n color: l.color,\n description: l.description,\n }));\n }\n\n // Comments\n async addComment(issueNumber: number, body: string): Promise<Comment> {\n const data = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/comments`,\n { body },\n )) as {\n id: number;\n body: string;\n user: { login: string; id: number; type: string };\n created_at: string;\n updated_at: string;\n html_url: string;\n };\n\n return {\n id: String(data.id),\n body: data.body,\n author: {\n login: data.user.login,\n id: String(data.user.id),\n type: data.user.type === 'Bot' ? 'Bot' : 'User',\n },\n createdAt: new Date(data.created_at),\n updatedAt: new Date(data.updated_at),\n url: data.html_url,\n };\n }\n\n async updateComment(commentId: string, body: string): Promise<Comment> {\n const data = (await this.rest.patch(\n `/repos/${this.owner}/${this.repo}/issues/comments/${commentId}`,\n { body },\n )) as ReturnType<typeof this.addComment> extends Promise<infer T>\n ? T\n : never;\n return data as Comment;\n }\n\n async deleteComment(commentId: string): Promise<void> {\n await this.rest.delete(\n `/repos/${this.owner}/${this.repo}/issues/comments/${commentId}`,\n );\n }\n\n async listComments(issueNumber: number): Promise<Comment[]> {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/comments`,\n )) as Array<{\n id: number;\n body: string;\n user: { login: string; id: number; type: string };\n created_at: string;\n updated_at: string;\n html_url: string;\n }>;\n\n return data.map((c) => ({\n id: String(c.id),\n body: c.body,\n author: {\n login: c.user.login,\n id: String(c.user.id),\n type: c.user.type === 'Bot' ? 'Bot' : 'User',\n },\n createdAt: new Date(c.created_at),\n updatedAt: new Date(c.updated_at),\n url: c.html_url,\n }));\n }\n\n // Assignments\n async assignIssue(issueNumber: number, assignees: string[]): Promise<void> {\n await this.rest.post(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/assignees`,\n { assignees },\n );\n }\n\n async unassignIssue(issueNumber: number, assignees: string[]): Promise<void> {\n await this.rest.delete(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/assignees`,\n );\n }\n\n // Pull Requests\n async getPullRequest(number: number): Promise<PullRequest> {\n const issue = await this.getIssue(number);\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/pulls/${number}`,\n )) as {\n head: { ref: string };\n base: { ref: string };\n merged: boolean;\n merged_at: string | null;\n mergeable: boolean;\n draft: boolean;\n };\n\n return {\n ...issue,\n headRef: data.head.ref,\n baseRef: data.base.ref,\n merged: data.merged,\n mergedAt: data.merged_at ? new Date(data.merged_at) : undefined,\n mergeable: data.mergeable,\n draft: data.draft,\n };\n }\n\n async createPullRequest(data: CreatePRInput): Promise<PullRequest> {\n const result = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/pulls`,\n {\n title: data.title,\n body: data.body,\n head: data.headRef,\n base: data.baseRef,\n draft: data.draft,\n },\n )) as { number: number };\n return this.getPullRequest(result.number);\n }\n\n async mergePullRequest(number: number, method?: MergeMethod): Promise<void> {\n await this.rest.put(\n `/repos/${this.owner}/${this.repo}/pulls/${number}/merge`,\n {\n merge_method: method || 'merge',\n },\n );\n }\n\n // Search\n async searchIssues(query: string, filters?: SearchFilters): Promise<Issue[]> {\n let searchQuery = `${query} repo:${this.owner}/${this.repo}`;\n\n if (filters?.state) {\n searchQuery += ` state:${filters.state}`;\n }\n if (filters?.labels) {\n searchQuery += ` ${filters.labels.map((l) => `label:\"${l}\"`).join(' ')}`;\n }\n if (filters?.author) {\n searchQuery += ` author:${filters.author}`;\n }\n if (filters?.assignee) {\n searchQuery += ` assignee:${filters.assignee}`;\n }\n\n const params = new URLSearchParams({\n q: searchQuery,\n sort: filters?.sort || 'created',\n order: filters?.order || 'desc',\n per_page: String(filters?.limit || 30),\n });\n\n const data = (await this.rest.get(`/search/issues?${params}`)) as {\n items: Array<{\n number: number;\n }>;\n };\n\n return Promise.all(data.items.map((item) => this.getIssue(item.number)));\n }\n\n // Node ID resolution\n async getIssueNodeId(issueNumber: number): Promise<string> {\n const issue = await this.getIssue(issueNumber);\n return issue.id;\n }\n\n async getPRNodeId(prNumber: number): Promise<string> {\n const pr = await this.getPullRequest(prNumber);\n return pr.id;\n }\n\n // Branch Management\n async createBranch(name: string, fromRef: string): Promise<Branch> {\n // First get the SHA for the reference\n const refData = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/git/ref/heads/${fromRef}`,\n )) as { object: { sha: string } };\n\n // Create the new branch\n await this.rest.post(`/repos/${this.owner}/${this.repo}/git/refs`, {\n ref: `refs/heads/${name}`,\n sha: refData.object.sha,\n });\n\n return {\n name,\n sha: refData.object.sha,\n protected: false,\n };\n }\n\n async deleteBranch(name: string): Promise<void> {\n await this.rest.delete(\n `/repos/${this.owner}/${this.repo}/git/refs/heads/${name}`,\n );\n }\n\n async getBranch(name: string): Promise<Branch | null> {\n try {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/branches/${encodeURIComponent(name)}`,\n )) as {\n name: string;\n commit: { sha: string };\n protected: boolean;\n };\n\n return {\n name: data.name,\n sha: data.commit.sha,\n protected: data.protected,\n };\n } catch (error) {\n // Return null if branch not found (404)\n if (\n error instanceof Error &&\n 'code' in error &&\n (error as { code: string }).code === 'NOT_FOUND'\n ) {\n return null;\n }\n throw error;\n }\n }\n\n // PR Draft/Review\n async markPRReady(prNumber: number): Promise<void> {\n const pr = await this.getPullRequest(prNumber);\n const mutation = `\n mutation($pullRequestId: ID!) {\n markPullRequestReadyForReview(input: {\n pullRequestId: $pullRequestId\n }) {\n pullRequest {\n id\n }\n }\n }\n `;\n await this.graphql.mutate(mutation, { pullRequestId: pr.id });\n }\n\n async convertPRToDraft(prNumber: number): Promise<void> {\n const pr = await this.getPullRequest(prNumber);\n const mutation = `\n mutation($pullRequestId: ID!) {\n convertPullRequestToDraft(input: {\n pullRequestId: $pullRequestId\n }) {\n pullRequest {\n id\n }\n }\n }\n `;\n await this.graphql.mutate(mutation, { pullRequestId: pr.id });\n }\n\n async requestReview(prNumber: number, reviewers: string[]): Promise<void> {\n await this.rest.post(\n `/repos/${this.owner}/${this.repo}/pulls/${prNumber}/requested_reviewers`,\n { reviewers },\n );\n }\n\n // Workflow\n async triggerWorkflow(\n workflowId: string,\n ref: string,\n inputs?: Record<string, string>,\n ): Promise<void> {\n await this.rest.post(\n `/repos/${this.owner}/${this.repo}/actions/workflows/${workflowId}/dispatches`,\n { ref, inputs: inputs || {} },\n );\n }\n\n // Linking\n async findPRsForIssue(issueNumber: number): Promise<PullRequest[]> {\n // Search for PRs that reference this issue with closing keywords\n const keywords = ['closes', 'fixes', 'resolves'];\n const searchTerms = keywords\n .map((k) => `${k} #${issueNumber}`)\n .join(' OR ');\n const query = `is:pr repo:${this.owner}/${this.repo} ${searchTerms}`;\n\n const data = (await this.rest.get(\n `/search/issues?q=${encodeURIComponent(query)}`,\n )) as {\n items: Array<{ number: number }>;\n };\n\n return Promise.all(\n data.items.map((item) => this.getPullRequest(item.number)),\n );\n }\n\n async findIssueForPR(prNumber: number): Promise<Issue | null> {\n const pr = await this.getPullRequest(prNumber);\n\n // Look for closing keywords in PR body\n const closingPattern = /(?:closes?|fixes?|resolves?)\\s+#(\\d+)/gi;\n const matches = [...pr.body.matchAll(closingPattern)];\n\n if (matches.length === 0) {\n return null;\n }\n\n // Return the first linked issue\n const issueNumber = Number.parseInt(matches[0][1], 10);\n try {\n return await this.getIssue(issueNumber);\n } catch {\n return null;\n }\n }\n\n // File Content\n async getFileContent(path: string, ref?: string): Promise<string | null> {\n try {\n const url = `/repos/${this.owner}/${this.repo}/contents/${path}${ref ? `?ref=${ref}` : ''}`;\n const data = (await this.rest.get(url)) as {\n type: string;\n content?: string;\n encoding?: string;\n };\n\n if (data.type !== 'file' || !data.content) {\n return null;\n }\n\n // GitHub returns base64-encoded content\n if (data.encoding === 'base64') {\n return Buffer.from(data.content, 'base64').toString('utf-8');\n }\n\n return data.content;\n } catch {\n // 404 means file doesn't exist\n return null;\n }\n }\n\n async listDirectoryFiles(path: string, ref?: string): Promise<string[]> {\n try {\n const url = `/repos/${this.owner}/${this.repo}/contents/${path}${ref ? `?ref=${ref}` : ''}`;\n const data = (await this.rest.get(url)) as Array<{\n name: string;\n type: string;\n }>;\n\n if (!Array.isArray(data)) {\n return [];\n }\n\n return data\n .filter((item) => item.type === 'file')\n .map((item) => item.name);\n } catch {\n // 404 means directory doesn't exist\n return [];\n }\n }\n\n // Repository Creation from Template\n\n /**\n * Create a new repository from this repository as a template.\n *\n * Uses the GitHub \"Generate\" API: POST /repos/{template_owner}/{template_repo}/generate\n * The current repository (this.owner/this.repo) is used as the template.\n */\n async createRepositoryFromTemplate(\n options: CreateFromTemplateOptions,\n ): Promise<Repository> {\n const data = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/generate`,\n {\n owner: options.owner,\n name: options.name,\n description: options.description || '',\n private: options.isPrivate ?? true,\n include_all_branches: options.includeAllBranches ?? false,\n },\n )) as {\n name: string;\n owner: { login: string };\n description: string;\n default_branch: string;\n html_url: string;\n private: boolean;\n };\n\n return {\n owner: data.owner.login,\n name: data.name,\n description: data.description || '',\n defaultBranch: data.default_branch,\n url: data.html_url,\n isPrivate: data.private,\n };\n }\n}\n","/**\n * Issue body parsing and rendering utilities\n *\n * Parses GitHub issue bodies created from YAML form templates.\n * GitHub renders form fields as markdown sections with ### headings.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport yaml from 'js-yaml';\nimport type { IRepository } from './types.js';\n\n/**\n * Template field definition - mirrors GitHub ISSUE_TEMPLATE YAML structure\n */\nexport interface TemplateField {\n type: 'textarea' | 'input' | 'dropdown' | 'checkboxes' | 'markdown';\n id?: string;\n attributes: {\n label: string;\n description?: string;\n placeholder?: string;\n value?: string;\n options?: string[];\n };\n validations?: {\n required?: boolean;\n };\n}\n\n/**\n * Issue template definition\n */\nexport interface IssueTemplate {\n name: string;\n description?: string;\n title?: string;\n labels?: string[];\n assignees?: string[];\n body: TemplateField[];\n}\n\n/**\n * Load and parse an issue template from a YAML file\n *\n * @param yamlPath - Path to the YAML template file\n * @returns Parsed issue template\n *\n * @example\n * ```typescript\n * const template = await loadIssueTemplate('.github/ISSUE_TEMPLATE/bug_report.yml');\n * ```\n */\nexport async function loadIssueTemplate(\n yamlPath: string,\n): Promise<IssueTemplate> {\n const content = await readFile(yamlPath, 'utf-8');\n return parseIssueTemplate(content);\n}\n\n/**\n * Parse an issue template from YAML content\n *\n * @param yamlContent - YAML content string\n * @returns Parsed issue template\n *\n * @example\n * ```typescript\n * const template = parseIssueTemplate(`\n * name: Bug Report\n * body:\n * - type: textarea\n * id: description\n * attributes:\n * label: Description\n * `);\n * ```\n */\nexport function parseIssueTemplate(yamlContent: string): IssueTemplate {\n const parsed = yaml.load(yamlContent) as IssueTemplate;\n\n if (!parsed.name) {\n throw new Error('Issue template must have a name');\n }\n\n if (!parsed.body || !Array.isArray(parsed.body)) {\n throw new Error('Issue template must have a body array');\n }\n\n return parsed;\n}\n\n/**\n * Parse an issue body into field values\n *\n * GitHub renders form fields as markdown sections:\n * ```\n * ### Label\n *\n * Content here\n *\n * ### Next Label\n * ```\n *\n * Without a template, returns a Record<string, string> keyed by label.\n * With a template, returns a Record<string, string> keyed by field ID.\n *\n * @param body - The issue body markdown\n * @param template - Optional template for mapping labels to field IDs\n * @returns Parsed fields as key-value pairs\n *\n * @example\n * ```typescript\n * // Without template - keyed by label\n * const fields = parseIssueBody(issue.body);\n * // { 'Description': '...', 'Steps to Reproduce': '...' }\n *\n * // With template - keyed by field ID\n * const template = await loadIssueTemplate('.github/ISSUE_TEMPLATE/bug_report.yml');\n * const fields = parseIssueBody(issue.body, template);\n * // { description: '...', reproduction: '...' }\n * ```\n */\nexport function parseIssueBody(\n body: string,\n template?: IssueTemplate,\n): Record<string, string> {\n const sections = parseSections(body);\n\n if (!template) {\n return sections;\n }\n\n // Build label-to-id mapping from template\n const labelToId = new Map<string, string>();\n for (const field of template.body) {\n if (field.id && field.attributes?.label) {\n labelToId.set(field.attributes.label, field.id);\n }\n }\n\n // Map labels to field IDs\n const result: Record<string, string> = {};\n for (const [label, content] of Object.entries(sections)) {\n const id = labelToId.get(label);\n if (id) {\n result[id] = content;\n } else {\n // Keep original label if no ID mapping found\n result[label] = content;\n }\n }\n\n return result;\n}\n\n/**\n * Parse markdown sections (### headers) into key-value pairs\n */\nfunction parseSections(body: string): Record<string, string> {\n const result: Record<string, string> = {};\n\n // Match ### headers and their content\n // Content is everything until the next ### or --- or end of string\n const sectionRegex =\n /^### (.+?)\\r?\\n\\r?\\n([\\s\\S]*?)(?=\\r?\\n### |\\r?\\n---|\\s*$)/gm;\n\n for (const match of body.matchAll(sectionRegex)) {\n const label = match[1].trim();\n const content = match[2].trim();\n result[label] = content;\n }\n\n return result;\n}\n\n/**\n * Render fields into an issue body markdown string\n *\n * Without a template, uses field keys as labels.\n * With a template, uses field IDs to look up labels and renders in template order.\n *\n * @param fields - Field values as key-value pairs\n * @param template - Optional template for field ordering and labels\n * @returns Markdown string for issue body\n *\n * @example\n * ```typescript\n * // Without template\n * const body = renderIssueBody({\n * 'Description': 'Bug description here',\n * 'Steps to Reproduce': '1. Do X\\n2. See error'\n * });\n *\n * // With template\n * const template = await loadIssueTemplate('.github/ISSUE_TEMPLATE/bug_report.yml');\n * const body = renderIssueBody({\n * description: 'Bug description here',\n * reproduction: '1. Do X\\n2. See error'\n * }, template);\n * ```\n */\nexport function renderIssueBody(\n fields: Record<string, string>,\n template?: IssueTemplate,\n): string {\n const sections: string[] = [];\n\n if (!template) {\n // Without template, render in field order\n for (const [label, content] of Object.entries(fields)) {\n sections.push(`### ${label}\\n\\n${content}`);\n }\n } else {\n // With template, render in template order using field IDs\n const idToContent = new Map(Object.entries(fields));\n\n for (const field of template.body) {\n // Skip markdown-only fields (no id)\n if (!field.id || field.type === 'markdown') {\n continue;\n }\n\n const label = field.attributes?.label || field.id;\n const content = idToContent.get(field.id);\n\n if (content !== undefined) {\n sections.push(`### ${label}\\n\\n${content}`);\n }\n }\n }\n\n return sections.join('\\n\\n');\n}\n\n/**\n * Get a specific field value from an issue body\n *\n * @param body - The issue body markdown\n * @param fieldIdOrLabel - Field ID (with template) or label (without template)\n * @param template - Optional template for field ID lookup\n * @returns Field value or undefined if not found\n */\nexport function getIssueField(\n body: string,\n fieldIdOrLabel: string,\n template?: IssueTemplate,\n): string | undefined {\n const fields = parseIssueBody(body, template);\n return fields[fieldIdOrLabel];\n}\n\n/**\n * Update a specific field in an issue body\n *\n * @param body - The issue body markdown\n * @param fieldIdOrLabel - Field ID (with template) or label (without template)\n * @param value - New value for the field\n * @param template - Optional template for field ID lookup\n * @returns Updated issue body markdown\n */\nexport function updateIssueField(\n body: string,\n fieldIdOrLabel: string,\n value: string,\n template?: IssueTemplate,\n): string {\n const fields = parseIssueBody(body, template);\n fields[fieldIdOrLabel] = value;\n return renderIssueBody(fields, template);\n}\n\n/**\n * Fetch issue templates from a repository via GitHub API\n *\n * @param repo - Repository client implementing IRepository\n * @returns Array of parsed issue templates\n *\n * @example\n * ```typescript\n * const repo = await getRepository({ type: 'github', owner: 'org', repo: 'name', token });\n * const templates = await fetchIssueTemplates(repo);\n * // [{ name: 'Bug Report', labels: ['bug'], body: [...] }, ...]\n * ```\n */\nexport async function fetchIssueTemplates(\n repo: IRepository,\n): Promise<IssueTemplate[]> {\n const templatePath = '.github/ISSUE_TEMPLATE';\n const files = await repo.listDirectoryFiles(templatePath);\n const templates: IssueTemplate[] = [];\n\n for (const file of files) {\n if (file.endsWith('.yml') || file.endsWith('.yaml')) {\n const content = await repo.getFileContent(`${templatePath}/${file}`);\n if (content) {\n try {\n templates.push(parseIssueTemplate(content));\n } catch (e) {\n console.warn(`[repos] Failed to parse template ${file}:`, e);\n }\n }\n }\n }\n\n return templates;\n}\n\n/**\n * Detect which template an issue was created from based on labels\n *\n * Matches issue labels against template labels to find the best match.\n * Returns the template with the most matching labels.\n *\n * @param labels - Issue labels\n * @param templates - Available templates\n * @returns Matching template or undefined if no match\n *\n * @example\n * ```typescript\n * const templates = await fetchIssueTemplates(repo);\n * const template = detectTemplateFromLabels(['bug', 'critical'], templates);\n * if (template) {\n * const fields = parseIssueBody(issue.body, template);\n * }\n * ```\n */\nexport function detectTemplateFromLabels(\n labels: string[],\n templates: IssueTemplate[],\n): IssueTemplate | undefined {\n const labelSet = new Set(labels.map((l) => l.toLowerCase()));\n\n let bestMatch: IssueTemplate | undefined;\n let bestScore = 0;\n\n for (const template of templates) {\n if (!template.labels || template.labels.length === 0) continue;\n\n const matchCount = template.labels.filter((l) =>\n labelSet.has(l.toLowerCase()),\n ).length;\n\n // Require at least one matching label\n if (matchCount > 0 && matchCount > bestScore) {\n bestScore = matchCount;\n bestMatch = template;\n }\n }\n\n return bestMatch;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAIA,IAAY,sBAAL,yBAAA,qBAAA;CACL,oBAAA,eAAA;CACA,oBAAA,kBAAA;CACA,oBAAA,eAAA;CACA,oBAAA,kBAAA;CACA,oBAAA,sBAAA;CACA,oBAAA,mBAAA;CACA,oBAAA,aAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAa,kBAAb,MAAa,wBAAwB,MAAM;CAGhC;CACA;CACA;CAJT,YACE,SACA,MACA,YACA,UACA;EACA,MAAM,OAAO;EAJN,KAAA,OAAA;EACA,KAAA,aAAA;EACA,KAAA,WAAA;EAGP,KAAK,OAAO;EACZ,MAAM,kBAAkB,MAAM,KAAK,WAAW;CAChD;CAEA,OAAO,eACL,YACA,SACA,UACiB;EACjB,IAAI;EAEJ,QAAQ,YAAR;GACE,KAAK;IACH,OAAA;IACA;GACF,KAAK;IACH,OAAA;IACA;GACF,KAAK;IACH,OAAA;IACA;GACF,KAAK;IACH,OAAA;IACA;GACF,KAAK;IACH,OAAA;IACA;GACF,SACE,OAAA;EACJ;EAEA,OAAO,IAAI,gBAAgB,SAAS,MAAM,YAAY,QAAQ;CAChE;CAEA,OAAO,aAAa,SAAiB,OAAgC;EACnE,OAAO,IAAI,gBACT,SAAA,iBAEA,KAAA,GACA,KACF;CACF;CAEA,cAAuB;EACrB,OACE,KAAK,SAAA,kBACL,KAAK,SAAA;CAET;AACF;;;;;;;;;;;AC3DA,SAAS,qBAAqB,OAAsC;CAClE,OACE,UAAU,QACV,OAAO,UAAU,YACjB,cAAc,SACd,iBAAiB,SACjB,eAAe,SACf,OAAQ,MAAsB,aAAa;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,eAAsB,cACpB,SACsB;CAEtB,IAAI,qBAAqB,OAAO,GAC9B,OAAO;CAIT,IAAI,CAAC,QAAQ,MACX,MAAM,IAAI,gBACR,+BACA,oBAAoB,gBACtB;CAGF,IAAI,CAAC,QAAQ,SAAS,CAAC,QAAQ,MAC7B,MAAM,IAAI,gBACR,0CACA,oBAAoB,gBACtB;CAGF,IAAI,CAAC,QAAQ,OACX,MAAM,IAAI,gBACR,oCACA,oBAAoB,YACtB;CAIF,QAAQ,QAAQ,MAAhB;EACE,KAAK,UAAU;GACb,MAAM,EAAE,qBAAqB,MAAA,QAAA,QAAA,CAAA,CAAA,WAAA,cAAA;GAC7B,OAAO,IAAI,iBAAiB,OAAO;EACrC;EAEA,KAAK,UACH,MAAM,IAAI,gBACR,sCACA,oBAAoB,OACtB;EAEF,KAAK,aACH,MAAM,IAAI,gBACR,yCACA,oBAAoB,OACtB;EAEF,KAAK,SACH,MAAM,IAAI,gBACR,4CACA,oBAAoB,OACtB;EAEF,SACE,MAAM,IAAI,gBACR,gCAAgC,QAAQ,QACxC,oBAAoB,gBACtB;CACJ;AACF;;;;;;;;;ACnGA,IAAa,aAAb,MAAwB;CACtB;CACA;CAEA,YAAY,QAA0B;EACpC,KAAK,QAAQ,OAAO;EACpB,KAAK,UAAU,OAAO,WAAW;CACnC;;;;CAKA,MAAM,QACJ,QACA,MACA,MACkB;EAClB,MAAM,MAAM,GAAG,KAAK,UAAU;EAC9B,MAAM,UAAU;GACd,eAAe,UAAU,KAAK;GAC9B,QAAQ;GACR,wBAAwB;GACxB,gBAAgB;EAClB;EAEA,MAAM,WAAW,MAAM,MAAM,KAAK;GAChC;GACA;GACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI,KAAA;EACtC,CAAC;EAED,IAAI,CAAC,SAAS,IAAI;GAChB,MAAM,QAAQ,MAAM,SAAS,KAAK;GAClC,MAAM,gBAAgB,eACpB,SAAS,QACT,qBAAqB,SAAS,WAAW,IAAI,SAC7C,KACF;EACF;EAEA,OAAO,SAAS,KAAK;CACvB;;;;CAKA,MAAM,IAAI,MAAgC;EACxC,OAAO,KAAK,QAAQ,OAAO,IAAI;CACjC;;;;CAKA,MAAM,KAAK,MAAc,MAAiC;EACxD,OAAO,KAAK,QAAQ,QAAQ,MAAM,IAAI;CACxC;;;;CAKA,MAAM,MAAM,MAAc,MAAiC;EACzD,OAAO,KAAK,QAAQ,SAAS,MAAM,IAAI;CACzC;;;;CAKA,MAAM,IAAI,MAAc,MAAkC;EACxD,OAAO,KAAK,QAAQ,OAAO,MAAM,IAAI;CACvC;;;;CAKA,MAAM,OAAO,MAA6B;EACxC,MAAM,KAAK,QAAQ,UAAU,IAAI;CACnC;AACF;;;;;;;;;;ACjEA,IAAa,mBAAb,MAAqD;CACnD;CACA;CACA;CACA;CAEA,YAAY,QAA0B;EACpC,IAAI,OAAO,SAAS,UAClB,MAAM,IAAI,MAAM,0CAA0C;EAG5D,KAAK,QAAQ,OAAO;EACpB,KAAK,OAAO,OAAO;EACnB,KAAK,OAAO,IAAI,WAAW;GACzB,OAAO,OAAO;GACd,SAAS,OAAO;EAClB,CAAC;EACD,KAAK,UAAU,IAAI,cAAc;GAC/B,UAAU,OAAO,UACb,GAAG,OAAO,QAAQ,YAClB;GACJ,OAAO,OAAO;EAChB,CAAC;CACH;CAGA,MAAM,gBAAqC;EACzC,MAAM,OAAQ,MAAM,KAAK,KAAK,IAAI,UAAU,KAAK,MAAM,GAAG,KAAK,MAAM;EASrE,OAAO;GACL,OAAO,KAAK,MAAM;GAClB,MAAM,KAAK;GACX,aAAa,KAAK;GAClB,eAAe,KAAK;GACpB,KAAK,KAAK;GACV,WAAW,KAAK;EAClB;CACF;CAGA,MAAM,SAAS,QAAgC;EAC7C,MAAM,OAAQ,MAAM,KAAK,KAAK,IAC5B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,QAC9C;EAgBA,OAAO;GACL,QAAQ,KAAK;GACb,IAAI,KAAK;GACT,OAAO,KAAK;GACZ,MAAM,KAAK,QAAQ;GACnB,OAAO,KAAK,UAAU,SAAS,SAAS;GACxC,QAAQ,KAAK,OAAO,KAAK,OAAO;IAC9B,MAAM,EAAE;IACR,OAAO,EAAE;IACT,aAAa,EAAE;GACjB,EAAE;GACF,WAAW,KAAK,UAAU,KAAK,OAAO;IACpC,OAAO,EAAE;IACT,IAAI,OAAO,EAAE,EAAE;IACf,MAAM,EAAE,SAAS,QAAQ,QAAQ;GACnC,EAAE;GACF,QAAQ;IACN,OAAO,KAAK,KAAK;IACjB,IAAI,OAAO,KAAK,KAAK,EAAE;IACvB,MAAM,KAAK,KAAK,SAAS,QAAQ,QAAQ;GAC3C;GACA,WAAW,IAAI,KAAK,KAAK,UAAU;GACnC,WAAW,IAAI,KAAK,KAAK,UAAU;GACnC,UAAU,KAAK,YAAY,IAAI,KAAK,KAAK,SAAS,IAAI,KAAA;GACtD,KAAK,KAAK;GACV,eAAe,KAAK;EACtB;CACF;CAEA,MAAM,YAAY,MAAwC;EACxD,MAAM,SAAU,MAAM,KAAK,KAAK,KAC9B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAClC,IACF;EACA,OAAO,KAAK,SAAS,OAAO,MAAM;CACpC;CAEA,MAAM,YAAY,QAAgB,MAAwC;EACxE,MAAM,KAAK,KAAK,MACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,UAC5C,IACF;EACA,OAAO,KAAK,SAAS,MAAM;CAC7B;CAEA,MAAM,WAAW,QAA+B;EAC9C,MAAM,KAAK,YAAY,QAAQ,EAAE,OAAO,SAAS,CAAC;CACpD;CAGA,MAAM,UAAU,aAAqB,QAAiC;EACpE,MAAM,KAAK,KAAK,KACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,YAAY,UACxD,EAAE,OAAO,CACX;CACF;CAEA,MAAM,YAAY,aAAqB,OAA8B;EACnE,MAAM,eAAe,mBAAmB,KAAK;EAC7C,MAAM,KAAK,KAAK,OACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,YAAY,UAAU,cACpE;CACF;CAEA,MAAM,YAAY,OAA6B;EAC7C,MAAM,KAAK,KAAK,KAAK,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,KAAK;CACxE;CAEA,MAAM,YAAY,MAAc,OAA6B;EAC3D,MAAM,KAAK,KAAK,MACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,mBAAmB,IAAI,KACnE,KACF;CACF;CAEA,MAAM,aAA+B;EAKnC,QAAO,MAJa,KAAK,KAAK,IAC5B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,QACpC,EAAA,CAEY,KAAK,OAAO;GACtB,MAAM,EAAE;GACR,OAAO,EAAE;GACT,aAAa,EAAE;EACjB,EAAE;CACJ;CAGA,MAAM,WAAW,aAAqB,MAAgC;EACpE,MAAM,OAAQ,MAAM,KAAK,KAAK,KAC5B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,YAAY,YACxD,EAAE,KAAK,CACT;EASA,OAAO;GACL,IAAI,OAAO,KAAK,EAAE;GAClB,MAAM,KAAK;GACX,QAAQ;IACN,OAAO,KAAK,KAAK;IACjB,IAAI,OAAO,KAAK,KAAK,EAAE;IACvB,MAAM,KAAK,KAAK,SAAS,QAAQ,QAAQ;GAC3C;GACA,WAAW,IAAI,KAAK,KAAK,UAAU;GACnC,WAAW,IAAI,KAAK,KAAK,UAAU;GACnC,KAAK,KAAK;EACZ;CACF;CAEA,MAAM,cAAc,WAAmB,MAAgC;EAOrE,OAAO,MANa,KAAK,KAAK,MAC5B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,mBAAmB,aACrD,EAAE,KAAK,CACT;CAIF;CAEA,MAAM,cAAc,WAAkC;EACpD,MAAM,KAAK,KAAK,OACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,mBAAmB,WACvD;CACF;CAEA,MAAM,aAAa,aAAyC;EAY1D,QAAO,MAXa,KAAK,KAAK,IAC5B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,YAAY,UAC1D,EAAA,CASY,KAAK,OAAO;GACtB,IAAI,OAAO,EAAE,EAAE;GACf,MAAM,EAAE;GACR,QAAQ;IACN,OAAO,EAAE,KAAK;IACd,IAAI,OAAO,EAAE,KAAK,EAAE;IACpB,MAAM,EAAE,KAAK,SAAS,QAAQ,QAAQ;GACxC;GACA,WAAW,IAAI,KAAK,EAAE,UAAU;GAChC,WAAW,IAAI,KAAK,EAAE,UAAU;GAChC,KAAK,EAAE;EACT,EAAE;CACJ;CAGA,MAAM,YAAY,aAAqB,WAAoC;EACzE,MAAM,KAAK,KAAK,KACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,YAAY,aACxD,EAAE,UAAU,CACd;CACF;CAEA,MAAM,cAAc,aAAqB,WAAoC;EAC3E,MAAM,KAAK,KAAK,OACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,UAAU,YAAY,WAC1D;CACF;CAGA,MAAM,eAAe,QAAsC;EACzD,MAAM,QAAQ,MAAM,KAAK,SAAS,MAAM;EACxC,MAAM,OAAQ,MAAM,KAAK,KAAK,IAC5B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,SAAS,QAC7C;EASA,OAAO;GACL,GAAG;GACH,SAAS,KAAK,KAAK;GACnB,SAAS,KAAK,KAAK;GACnB,QAAQ,KAAK;GACb,UAAU,KAAK,YAAY,IAAI,KAAK,KAAK,SAAS,IAAI,KAAA;GACtD,WAAW,KAAK;GAChB,OAAO,KAAK;EACd;CACF;CAEA,MAAM,kBAAkB,MAA2C;EACjE,MAAM,SAAU,MAAM,KAAK,KAAK,KAC9B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,SAClC;GACE,OAAO,KAAK;GACZ,MAAM,KAAK;GACX,MAAM,KAAK;GACX,MAAM,KAAK;GACX,OAAO,KAAK;EACd,CACF;EACA,OAAO,KAAK,eAAe,OAAO,MAAM;CAC1C;CAEA,MAAM,iBAAiB,QAAgB,QAAqC;EAC1E,MAAM,KAAK,KAAK,IACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,SAAS,OAAO,SAClD,EACE,cAAc,UAAU,QAC1B,CACF;CACF;CAGA,MAAM,aAAa,OAAe,SAA2C;EAC3E,IAAI,cAAc,GAAG,MAAM,QAAQ,KAAK,MAAM,GAAG,KAAK;EAEtD,IAAI,SAAS,OACX,eAAe,UAAU,QAAQ;EAEnC,IAAI,SAAS,QACX,eAAe,IAAI,QAAQ,OAAO,KAAK,MAAM,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG;EAEvE,IAAI,SAAS,QACX,eAAe,WAAW,QAAQ;EAEpC,IAAI,SAAS,UACX,eAAe,aAAa,QAAQ;EAGtC,MAAM,SAAS,IAAI,gBAAgB;GACjC,GAAG;GACH,MAAM,SAAS,QAAQ;GACvB,OAAO,SAAS,SAAS;GACzB,UAAU,OAAO,SAAS,SAAS,EAAE;EACvC,CAAC;EAED,MAAM,OAAQ,MAAM,KAAK,KAAK,IAAI,kBAAkB,QAAQ;EAM5D,OAAO,QAAQ,IAAI,KAAK,MAAM,KAAK,SAAS,KAAK,SAAS,KAAK,MAAM,CAAC,CAAC;CACzE;CAGA,MAAM,eAAe,aAAsC;EAEzD,QAAO,MADa,KAAK,SAAS,WAAW,EAAA,CAChC;CACf;CAEA,MAAM,YAAY,UAAmC;EAEnD,QAAO,MADU,KAAK,eAAe,QAAQ,EAAA,CACnC;CACZ;CAGA,MAAM,aAAa,MAAc,SAAkC;EAEjE,MAAM,UAAW,MAAM,KAAK,KAAK,IAC/B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,iBAAiB,SACrD;EAGA,MAAM,KAAK,KAAK,KAAK,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,YAAY;GACjE,KAAK,cAAc;GACnB,KAAK,QAAQ,OAAO;EACtB,CAAC;EAED,OAAO;GACL;GACA,KAAK,QAAQ,OAAO;GACpB,WAAW;EACb;CACF;CAEA,MAAM,aAAa,MAA6B;EAC9C,MAAM,KAAK,KAAK,OACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,kBAAkB,MACtD;CACF;CAEA,MAAM,UAAU,MAAsC;EACpD,IAAI;GACF,MAAM,OAAQ,MAAM,KAAK,KAAK,IAC5B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,YAAY,mBAAmB,IAAI,GACvE;GAMA,OAAO;IACL,MAAM,KAAK;IACX,KAAK,KAAK,OAAO;IACjB,WAAW,KAAK;GAClB;EACF,SAAS,OAAO;GAEd,IACE,iBAAiB,SACjB,UAAU,SACT,MAA2B,SAAS,aAErC,OAAO;GAET,MAAM;EACR;CACF;CAGA,MAAM,YAAY,UAAiC;EACjD,MAAM,KAAK,MAAM,KAAK,eAAe,QAAQ;EAY7C,MAAM,KAAK,QAAQ,OAAO;;;;;;;;;;OAAU,EAAE,eAAe,GAAG,GAAG,CAAC;CAC9D;CAEA,MAAM,iBAAiB,UAAiC;EACtD,MAAM,KAAK,MAAM,KAAK,eAAe,QAAQ;EAY7C,MAAM,KAAK,QAAQ,OAAO;;;;;;;;;;OAAU,EAAE,eAAe,GAAG,GAAG,CAAC;CAC9D;CAEA,MAAM,cAAc,UAAkB,WAAoC;EACxE,MAAM,KAAK,KAAK,KACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,SAAS,SAAS,uBACpD,EAAE,UAAU,CACd;CACF;CAGA,MAAM,gBACJ,YACA,KACA,QACe;EACf,MAAM,KAAK,KAAK,KACd,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,qBAAqB,WAAW,cAClE;GAAE;GAAK,QAAQ,UAAU,CAAC;EAAE,CAC9B;CACF;CAGA,MAAM,gBAAgB,aAA6C;EAGjE,MAAM,cAAc;GADF;GAAU;GAAS;EACjB,CAAA,CACjB,KAAK,MAAM,GAAG,EAAE,IAAI,aAAa,CAAC,CAClC,KAAK,MAAM;EACd,MAAM,QAAQ,cAAc,KAAK,MAAM,GAAG,KAAK,KAAK,GAAG;EAEvD,MAAM,OAAQ,MAAM,KAAK,KAAK,IAC5B,oBAAoB,mBAAmB,KAAK,GAC9C;EAIA,OAAO,QAAQ,IACb,KAAK,MAAM,KAAK,SAAS,KAAK,eAAe,KAAK,MAAM,CAAC,CAC3D;CACF;CAEA,MAAM,eAAe,UAAyC;EAK5D,MAAM,UAAU,CAAC,IAAG,MAJH,KAAK,eAAe,QAAQ,EAAA,CAItB,KAAK,SAAS,yCAAc,CAAC;EAEpD,IAAI,QAAQ,WAAW,GACrB,OAAO;EAIT,MAAM,cAAc,OAAO,SAAS,QAAQ,EAAE,CAAC,IAAI,EAAE;EACrD,IAAI;GACF,OAAO,MAAM,KAAK,SAAS,WAAW;EACxC,QAAQ;GACN,OAAO;EACT;CACF;CAGA,MAAM,eAAe,MAAc,KAAsC;EACvE,IAAI;GACF,MAAM,MAAM,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,YAAY,OAAO,MAAM,QAAQ,QAAQ;GACvF,MAAM,OAAQ,MAAM,KAAK,KAAK,IAAI,GAAG;GAMrC,IAAI,KAAK,SAAS,UAAU,CAAC,KAAK,SAChC,OAAO;GAIT,IAAI,KAAK,aAAa,UACpB,OAAO,OAAO,KAAK,KAAK,SAAS,QAAQ,CAAC,CAAC,SAAS,OAAO;GAG7D,OAAO,KAAK;EACd,QAAQ;GAEN,OAAO;EACT;CACF;CAEA,MAAM,mBAAmB,MAAc,KAAiC;EACtE,IAAI;GACF,MAAM,MAAM,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,YAAY,OAAO,MAAM,QAAQ,QAAQ;GACvF,MAAM,OAAQ,MAAM,KAAK,KAAK,IAAI,GAAG;GAKrC,IAAI,CAAC,MAAM,QAAQ,IAAI,GACrB,OAAO,CAAC;GAGV,OAAO,KACJ,QAAQ,SAAS,KAAK,SAAS,MAAM,CAAC,CACtC,KAAK,SAAS,KAAK,IAAI;EAC5B,QAAQ;GAEN,OAAO,CAAC;EACV;CACF;;;;;;;CAUA,MAAM,6BACJ,SACqB;EACrB,MAAM,OAAQ,MAAM,KAAK,KAAK,KAC5B,UAAU,KAAK,MAAM,GAAG,KAAK,KAAK,YAClC;GACE,OAAO,QAAQ;GACf,MAAM,QAAQ;GACd,aAAa,QAAQ,eAAe;GACpC,SAAS,QAAQ,aAAa;GAC9B,sBAAsB,QAAQ,sBAAsB;EACtD,CACF;EASA,OAAO;GACL,OAAO,KAAK,MAAM;GAClB,MAAM,KAAK;GACX,aAAa,KAAK,eAAe;GACjC,eAAe,KAAK;GACpB,KAAK,KAAK;GACV,WAAW,KAAK;EAClB;CACF;AACF;;;;;;;;;;;;;;;;;;;;ACthBA,eAAsB,kBACpB,UACwB;CAExB,OAAO,mBAAmB,MADJ,SAAS,UAAU,OAAO,CACf;AACnC;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,mBAAmB,aAAoC;CACrE,MAAM,SAAS,KAAK,KAAK,WAAW;CAEpC,IAAI,CAAC,OAAO,MACV,MAAM,IAAI,MAAM,iCAAiC;CAGnD,IAAI,CAAC,OAAO,QAAQ,CAAC,MAAM,QAAQ,OAAO,IAAI,GAC5C,MAAM,IAAI,MAAM,uCAAuC;CAGzD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,eACd,MACA,UACwB;CACxB,MAAM,WAAW,cAAc,IAAI;CAEnC,IAAI,CAAC,UACH,OAAO;CAIT,MAAM,4BAAY,IAAI,IAAoB;CAC1C,KAAK,MAAM,SAAS,SAAS,MAC3B,IAAI,MAAM,MAAM,MAAM,YAAY,OAChC,UAAU,IAAI,MAAM,WAAW,OAAO,MAAM,EAAE;CAKlD,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,QAAQ,GAAG;EACvD,MAAM,KAAK,UAAU,IAAI,KAAK;EAC9B,IAAI,IACF,OAAO,MAAM;OAGb,OAAO,SAAS;CAEpB;CAEA,OAAO;AACT;;;;AAKA,SAAS,cAAc,MAAsC;CAC3D,MAAM,SAAiC,CAAC;CAOxC,KAAK,MAAM,SAAS,KAAK,SAAS,6DAAY,GAAG;EAC/C,MAAM,QAAQ,MAAM,EAAE,CAAC,KAAK;EAE5B,OAAO,SADS,MAAM,EAAE,CAAC,KACT;CAClB;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,gBACd,QACA,UACQ;CACR,MAAM,WAAqB,CAAC;CAE5B,IAAI,CAAC,UAEH,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,MAAM,GAClD,SAAS,KAAK,OAAO,MAAM,MAAM,SAAS;MAEvC;EAEL,MAAM,cAAc,IAAI,IAAI,OAAO,QAAQ,MAAM,CAAC;EAElD,KAAK,MAAM,SAAS,SAAS,MAAM;GAEjC,IAAI,CAAC,MAAM,MAAM,MAAM,SAAS,YAC9B;GAGF,MAAM,QAAQ,MAAM,YAAY,SAAS,MAAM;GAC/C,MAAM,UAAU,YAAY,IAAI,MAAM,EAAE;GAExC,IAAI,YAAY,KAAA,GACd,SAAS,KAAK,OAAO,MAAM,MAAM,SAAS;EAE9C;CACF;CAEA,OAAO,SAAS,KAAK,MAAM;AAC7B;;;;;;;;;AAUA,SAAgB,cACd,MACA,gBACA,UACoB;CAEpB,OADe,eAAe,MAAM,QAC7B,CAAA,CAAO;AAChB;;;;;;;;;;AAWA,SAAgB,iBACd,MACA,gBACA,OACA,UACQ;CACR,MAAM,SAAS,eAAe,MAAM,QAAQ;CAC5C,OAAO,kBAAkB;CACzB,OAAO,gBAAgB,QAAQ,QAAQ;AACzC;;;;;;;;;;;;;;AAeA,eAAsB,oBACpB,MAC0B;CAC1B,MAAM,eAAe;CACrB,MAAM,QAAQ,MAAM,KAAK,mBAAmB,YAAY;CACxD,MAAM,YAA6B,CAAC;CAEpC,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,OAAO,GAAG;EACnD,MAAM,UAAU,MAAM,KAAK,eAAe,GAAG,aAAa,GAAG,MAAM;EACnE,IAAI,SACF,IAAI;GACF,UAAU,KAAK,mBAAmB,OAAO,CAAC;EAC5C,SAAS,GAAG;GACV,QAAQ,KAAK,oCAAoC,KAAK,IAAI,CAAC;EAC7D;CAEJ;CAGF,OAAO;AACT;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,yBACd,QACA,WAC2B;CAC3B,MAAM,WAAW,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,YAAY,CAAC,CAAC;CAE3D,IAAI;CACJ,IAAI,YAAY;CAEhB,KAAK,MAAM,YAAY,WAAW;EAChC,IAAI,CAAC,SAAS,UAAU,SAAS,OAAO,WAAW,GAAG;EAEtD,MAAM,aAAa,SAAS,OAAO,QAAQ,MACzC,SAAS,IAAI,EAAE,YAAY,CAAC,CAC9B,CAAC,CAAC;EAGF,IAAI,aAAa,KAAK,aAAa,WAAW;GAC5C,YAAY;GACZ,YAAY;EACd;CACF;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/errors.ts","../src/factory.ts","../src/forge/errors.ts","../src/github/forge.ts","../src/github/transport.ts","../src/github/app.ts","../src/github/fixtures.ts","../src/github/rest.ts","../src/github/index.ts","../src/github/webhooks.ts","../src/parsing.ts"],"sourcesContent":["/**\n * Repository error handling\n */\n\nexport enum RepositoryErrorCode {\n NOT_FOUND = 'NOT_FOUND',\n UNAUTHORIZED = 'UNAUTHORIZED',\n FORBIDDEN = 'FORBIDDEN',\n RATE_LIMITED = 'RATE_LIMITED',\n VALIDATION_ERROR = 'VALIDATION_ERROR',\n NETWORK_ERROR = 'NETWORK_ERROR',\n UNKNOWN = 'UNKNOWN',\n}\n\nexport class RepositoryError extends Error {\n constructor(\n message: string,\n public code: RepositoryErrorCode,\n public statusCode?: number,\n public response?: unknown,\n ) {\n super(message);\n this.name = 'RepositoryError';\n Error.captureStackTrace(this, this.constructor);\n }\n\n static fromHTTPStatus(\n statusCode: number,\n message: string,\n response?: unknown,\n ): RepositoryError {\n let code: RepositoryErrorCode;\n\n switch (statusCode) {\n case 404:\n code = RepositoryErrorCode.NOT_FOUND;\n break;\n case 401:\n code = RepositoryErrorCode.UNAUTHORIZED;\n break;\n case 403:\n code = RepositoryErrorCode.FORBIDDEN;\n break;\n case 429:\n code = RepositoryErrorCode.RATE_LIMITED;\n break;\n case 422:\n code = RepositoryErrorCode.VALIDATION_ERROR;\n break;\n default:\n code = RepositoryErrorCode.UNKNOWN;\n }\n\n return new RepositoryError(message, code, statusCode, response);\n }\n\n static networkError(message: string, cause?: Error): RepositoryError {\n return new RepositoryError(\n message,\n RepositoryErrorCode.NETWORK_ERROR,\n undefined,\n cause,\n );\n }\n\n isRetryable(): boolean {\n return (\n this.code === RepositoryErrorCode.RATE_LIMITED ||\n this.code === RepositoryErrorCode.NETWORK_ERROR\n );\n }\n}\n","/**\n * Repository factory function\n *\n * Creates repository instances following the pattern from @happyvertical/files and @happyvertical/sql\n */\n\nimport { RepositoryError, RepositoryErrorCode } from './errors.js';\nimport type { IRepository, RepositoryConfig } from './types.js';\n\n/**\n * Check if value is already a repository instance\n */\nfunction isRepositoryInstance(value: unknown): value is IRepository {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'getIssue' in value &&\n 'createIssue' in value &&\n 'addLabels' in value &&\n typeof (value as IRepository).getIssue === 'function'\n );\n}\n\n/**\n * Get a repository client instance\n *\n * This is the main entry point following the pattern from @happyvertical/files and @happyvertical/sql.\n * It can accept either a configuration object or an existing repository instance.\n *\n * @param options - Repository configuration or existing repository instance\n * @returns Promise resolving to repository interface\n *\n * @example\n * ```typescript\n * import { getRepository } from '@happyvertical/repos';\n *\n * // Create a GitHub repository client\n * const repo = await getRepository({\n * type: 'github',\n * owner: 'happyvertical',\n * repo: 'sdk',\n * token: process.env.GITHUB_TOKEN\n * });\n *\n * // Use the client\n * const issue = await repo.getIssue(352);\n * await repo.addLabels(352, ['type: feature', 'priority: high']);\n *\n * // Pass existing instance (returns it unchanged)\n * const sameRepo = await getRepository(repo);\n * ```\n */\nexport async function getRepository(\n options: RepositoryConfig | IRepository,\n): Promise<IRepository> {\n // If already a repository instance, return it\n if (isRepositoryInstance(options)) {\n return options;\n }\n\n // Validate configuration\n if (!options.type) {\n throw new RepositoryError(\n 'Repository type is required',\n RepositoryErrorCode.VALIDATION_ERROR,\n );\n }\n\n if (!options.owner || !options.repo) {\n throw new RepositoryError(\n 'Repository owner and repo are required',\n RepositoryErrorCode.VALIDATION_ERROR,\n );\n }\n\n if (!options.token) {\n throw new RepositoryError(\n 'Authentication token is required',\n RepositoryErrorCode.UNAUTHORIZED,\n );\n }\n\n // Create repository instance based on type\n switch (options.type) {\n case 'github': {\n const { GitHubRepository } = await import('./github/index.js');\n return new GitHubRepository(options);\n }\n\n case 'gitlab':\n throw new RepositoryError(\n 'GitLab support not yet implemented',\n RepositoryErrorCode.UNKNOWN,\n );\n\n case 'bitbucket':\n throw new RepositoryError(\n 'Bitbucket support not yet implemented',\n RepositoryErrorCode.UNKNOWN,\n );\n\n case 'azure':\n throw new RepositoryError(\n 'Azure DevOps support not yet implemented',\n RepositoryErrorCode.UNKNOWN,\n );\n\n default:\n throw new RepositoryError(\n `Unsupported repository type: ${options.type}`,\n RepositoryErrorCode.VALIDATION_ERROR,\n );\n }\n}\n","import type { ForgeProvider, ForgeRateLimit } from './types.js';\n\nexport type ForgeErrorCode =\n | 'AUTHENTICATION_FAILED'\n | 'AUTHORITY_MISMATCH'\n | 'CONFIGURATION_ERROR'\n | 'INVALID_INPUT'\n | 'NOT_FOUND'\n | 'PROVIDER_ERROR'\n | 'RATE_LIMITED'\n | 'SIGNATURE_INVALID'\n | 'TRANSPORT_ERROR';\n\nexport class ForgeError extends Error {\n readonly provider?: ForgeProvider;\n readonly code: ForgeErrorCode;\n readonly status?: number;\n readonly requestId?: string;\n readonly rateLimit?: ForgeRateLimit;\n readonly details?: unknown;\n readonly retryable: boolean;\n\n constructor(\n message: string,\n code: ForgeErrorCode,\n options: {\n cause?: unknown;\n provider?: ForgeProvider;\n status?: number;\n requestId?: string;\n rateLimit?: ForgeRateLimit;\n details?: unknown;\n retryable?: boolean;\n } = {},\n ) {\n super(\n message,\n options.cause === undefined ? undefined : { cause: options.cause },\n );\n this.name = 'ForgeError';\n this.code = code;\n this.provider = options.provider;\n this.status = options.status;\n this.requestId = options.requestId;\n this.rateLimit = options.rateLimit;\n this.details = options.details;\n this.retryable = options.retryable ?? false;\n }\n}\n\nexport class ForgeSignatureError extends ForgeError {\n constructor(message = 'Forge webhook signature is invalid') {\n super(message, 'SIGNATURE_INVALID');\n this.name = 'ForgeSignatureError';\n }\n}\n","import type {\n CheckRun,\n CommitStatus,\n CreateCheckRunInput,\n CreateCommitStatusInput,\n ForgeOperations,\n ForgePullRequestRef,\n ForgeRepositoryRef,\n ForgeResponse,\n ForgeTransport,\n UpdateCheckRunInput,\n} from '../forge/types.js';\n\n/** Repository coordinates and transport for a GitHub forge provider. */\nexport interface GitHubForgeProviderOptions {\n owner: string;\n repo: string;\n transport: ForgeTransport;\n}\n\nfunction repositoryPath(owner: string, repo: string): string {\n return `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`;\n}\n\nfunction normalizeRepository(\n data: Record<string, unknown>,\n): ForgeRepositoryRef {\n const owner = (data.owner as { login?: string } | undefined)?.login ?? '';\n const name = typeof data.name === 'string' ? data.name : '';\n return {\n id: data.node_id === undefined ? undefined : String(data.node_id),\n owner,\n name,\n fullName:\n typeof data.full_name === 'string' ? data.full_name : `${owner}/${name}`,\n defaultBranch:\n typeof data.default_branch === 'string' ? data.default_branch : undefined,\n private: typeof data.private === 'boolean' ? data.private : undefined,\n url: typeof data.html_url === 'string' ? data.html_url : undefined,\n };\n}\n\nfunction normalizePullRequest(\n data: Record<string, unknown>,\n): ForgePullRequestRef {\n const head = (data.head ?? {}) as Record<string, unknown>;\n const base = (data.base ?? {}) as Record<string, unknown>;\n return {\n id: data.node_id === undefined ? undefined : String(data.node_id),\n number: Number(data.number),\n state: data.state === 'closed' ? 'closed' : 'open',\n draft: typeof data.draft === 'boolean' ? data.draft : undefined,\n headSha: String(head.sha ?? ''),\n headRef: typeof head.ref === 'string' ? head.ref : undefined,\n baseSha: typeof base.sha === 'string' ? base.sha : undefined,\n baseRef: typeof base.ref === 'string' ? base.ref : undefined,\n merged: typeof data.merged === 'boolean' ? data.merged : undefined,\n mergeCommitSha:\n typeof data.merge_commit_sha === 'string'\n ? data.merge_commit_sha\n : undefined,\n url: typeof data.html_url === 'string' ? data.html_url : undefined,\n };\n}\n\nfunction normalizeStatus(data: Record<string, unknown>): CommitStatus {\n return {\n id: String(data.id ?? data.node_id ?? ''),\n sha: String(data.sha ?? ''),\n state: String(data.state ?? ''),\n context: String(data.context ?? ''),\n description:\n typeof data.description === 'string' ? data.description : undefined,\n targetUrl:\n typeof data.target_url === 'string' ? data.target_url : undefined,\n createdAt:\n typeof data.created_at === 'string'\n ? new Date(data.created_at)\n : undefined,\n raw: data,\n };\n}\n\nfunction normalizeCheck(data: Record<string, unknown>): CheckRun {\n return {\n id: String(data.id ?? data.node_id ?? ''),\n name: String(data.name ?? ''),\n headSha: String(data.head_sha ?? ''),\n status: (data.status ?? 'queued') as CheckRun['status'],\n conclusion:\n typeof data.conclusion === 'string'\n ? (data.conclusion as CheckRun['conclusion'])\n : undefined,\n detailsUrl:\n typeof data.details_url === 'string' ? data.details_url : undefined,\n externalId:\n typeof data.external_id === 'string' ? data.external_id : undefined,\n startedAt:\n typeof data.started_at === 'string'\n ? new Date(data.started_at)\n : undefined,\n completedAt:\n typeof data.completed_at === 'string'\n ? new Date(data.completed_at)\n : undefined,\n raw: data,\n };\n}\n\nfunction checkInput(input: CreateCheckRunInput | UpdateCheckRunInput) {\n return {\n ...('name' in input ? { name: input.name } : {}),\n ...('headSha' in input ? { head_sha: input.headSha } : {}),\n status: input.status,\n conclusion: input.conclusion,\n details_url: input.detailsUrl,\n external_id: input.externalId,\n started_at:\n input.startedAt instanceof Date\n ? input.startedAt.toISOString()\n : input.startedAt,\n completed_at:\n input.completedAt instanceof Date\n ? input.completedAt.toISOString()\n : input.completedAt,\n output: input.output,\n };\n}\n\n/**\n * Repository-scoped GitHub implementation of provider-neutral forge operations.\n * Every operation may throw `ForgeError` for transport or provider failures.\n */\nexport class GitHubForgeProvider implements ForgeOperations {\n private readonly transport: ForgeTransport;\n private readonly path: string;\n\n /**\n * Creates a repository-scoped GitHub forge provider.\n * @param options Repository coordinates and authenticated transport.\n */\n constructor(options: GitHubForgeProviderOptions) {\n this.transport = options.transport;\n this.path = repositoryPath(options.owner, options.repo);\n }\n\n /** @returns Normalized repository data and request metadata. */\n async getRepository(): Promise<ForgeResponse<ForgeRepositoryRef>> {\n const response = await this.transport.request<Record<string, unknown>>({\n method: 'GET',\n path: this.path,\n });\n return { ...response, data: normalizeRepository(response.data) };\n }\n\n /**\n * Returns one normalized pull request.\n * @param number Repository-local pull-request number.\n * @returns Pull-request data and request metadata.\n * @throws {ForgeError} When GitHub rejects the request.\n */\n async getPullRequest(\n number: number,\n ): Promise<ForgeResponse<ForgePullRequestRef>> {\n const response = await this.transport.request<Record<string, unknown>>({\n method: 'GET',\n path: `${this.path}/pulls/${number}`,\n });\n return { ...response, data: normalizePullRequest(response.data) };\n }\n\n /**\n * Lists every raw provider review for one pull request.\n * @param number Repository-local pull-request number.\n * @returns All reviews and final-page request metadata.\n */\n listPullRequestReviews(\n number: number,\n ): Promise<ForgeResponse<readonly unknown[]>> {\n return this.paginate(\n `${this.path}/pulls/${number}/reviews`,\n (data) => data as unknown[],\n );\n }\n\n /**\n * Returns one raw provider commit payload.\n * @param sha Exact commit SHA.\n * @returns Commit payload and request metadata.\n */\n getCommit(sha: string): Promise<ForgeResponse<unknown>> {\n return this.transport.request({\n method: 'GET',\n path: `${this.path}/commits/${encodeURIComponent(sha)}`,\n });\n }\n\n /**\n * Returns complete normalized commit-status history.\n * @param sha Exact commit SHA.\n * @returns All status pages and final-page request metadata.\n */\n async listCommitStatuses(\n sha: string,\n ): Promise<ForgeResponse<readonly CommitStatus[]>> {\n return this.paginate(\n `${this.path}/commits/${encodeURIComponent(sha)}/statuses`,\n (data) => (data as Record<string, unknown>[]).map(normalizeStatus),\n );\n }\n\n /**\n * Publishes one commit status.\n * @param input Exact SHA and status attributes.\n * @returns Published status and request metadata.\n */\n async createCommitStatus(\n input: CreateCommitStatusInput,\n ): Promise<ForgeResponse<CommitStatus>> {\n const response = await this.transport.request<Record<string, unknown>>({\n method: 'POST',\n path: `${this.path}/statuses/${encodeURIComponent(input.sha)}`,\n body: {\n state: input.state,\n context: input.context,\n description: input.description,\n target_url: input.targetUrl,\n },\n });\n return { ...response, data: normalizeStatus(response.data) };\n }\n\n /**\n * Returns all normalized check runs, including reruns.\n * @param sha Exact commit SHA.\n * @returns All check pages and final-page request metadata.\n */\n async listCheckRuns(\n sha: string,\n ): Promise<ForgeResponse<readonly CheckRun[]>> {\n return this.paginate(\n `${this.path}/commits/${encodeURIComponent(sha)}/check-runs?filter=all`,\n (data) =>\n (\n (data as { check_runs?: Record<string, unknown>[] }).check_runs ?? []\n ).map(normalizeCheck),\n (data) => (data as { total_count?: number }).total_count,\n );\n }\n\n /**\n * Publishes one check run.\n * @param input Check identity, exact head SHA, state, and output.\n * @returns Published check and request metadata.\n */\n async createCheckRun(\n input: CreateCheckRunInput,\n ): Promise<ForgeResponse<CheckRun>> {\n const response = await this.transport.request<Record<string, unknown>>({\n method: 'POST',\n path: `${this.path}/check-runs`,\n body: checkInput(input),\n });\n return { ...response, data: normalizeCheck(response.data) };\n }\n\n /**\n * Changes one check run by provider ID.\n * @param id GitHub check-run ID.\n * @param input Attributes to change.\n * @returns Updated check and request metadata.\n */\n async updateCheckRun(\n id: string,\n input: UpdateCheckRunInput,\n ): Promise<ForgeResponse<CheckRun>> {\n const response = await this.transport.request<Record<string, unknown>>({\n method: 'PATCH',\n path: `${this.path}/check-runs/${encodeURIComponent(id)}`,\n body: checkInput(input),\n });\n return { ...response, data: normalizeCheck(response.data) };\n }\n\n /**\n * Lists raw deployment payloads using narrow filters.\n * @param options Optional SHA, environment, and result limit.\n * @returns Matching deployments and request metadata.\n */\n listDeployments(\n options: { sha?: string; environment?: string; limit?: number } = {},\n ): Promise<ForgeResponse<unknown[]>> {\n const params = new URLSearchParams();\n if (options.sha) params.set('sha', options.sha);\n if (options.environment) params.set('environment', options.environment);\n params.set('per_page', String(options.limit ?? 30));\n return this.transport.request({\n method: 'GET',\n path: `${this.path}/deployments?${params}`,\n });\n }\n\n /**\n * Returns one raw deployment payload.\n * @param id GitHub deployment ID.\n * @returns Deployment payload and request metadata.\n */\n getDeployment(id: string): Promise<ForgeResponse<unknown>> {\n return this.transport.request({\n method: 'GET',\n path: `${this.path}/deployments/${encodeURIComponent(id)}`,\n });\n }\n\n private async paginate<T>(\n path: string,\n items: (data: unknown) => readonly T[],\n totalCount?: (data: unknown) => number | undefined,\n ): Promise<ForgeResponse<readonly T[]>> {\n const separator = path.includes('?') ? '&' : '?';\n const collected: T[] = [];\n let page = 1;\n let response: ForgeResponse<unknown>;\n let providerTotal: number | undefined;\n do {\n response = await this.transport.request({\n method: 'GET',\n path: `${path}${separator}per_page=100&page=${page}`,\n });\n const pageItems = items(response.data);\n collected.push(...pageItems);\n providerTotal ??= totalCount?.(response.data);\n page += 1;\n if (pageItems.length < 100) break;\n } while (providerTotal === undefined || collected.length < providerTotal);\n\n return {\n data: collected,\n metadata: {\n ...response.metadata,\n pagination: {\n pages: page - 1,\n totalCount: providerTotal ?? collected.length,\n },\n },\n };\n }\n}\n","import { ForgeError, type ForgeErrorCode } from '../forge/errors.js';\nimport type {\n ForgeRateLimit,\n ForgeResponse,\n ForgeTransport,\n ForgeTransportRequest,\n} from '../forge/types.js';\n\nexport type GitHubTokenSource = string | (() => string | Promise<string>);\n\n/** Construction options for an authenticated GitHub REST transport. */\nexport interface GitHubTransportOptions {\n token: GitHubTokenSource;\n baseUrl?: string;\n fetch?: typeof globalThis.fetch;\n}\n\nfunction optionalInteger(value: string | null): number | undefined {\n if (value === null || value.trim() === '') return undefined;\n const parsed = Number.parseInt(value, 10);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction responseRateLimit(headers: Headers): ForgeRateLimit | undefined {\n const limit = optionalInteger(headers.get('x-ratelimit-limit'));\n const remaining = optionalInteger(headers.get('x-ratelimit-remaining'));\n const used = optionalInteger(headers.get('x-ratelimit-used'));\n const reset = optionalInteger(headers.get('x-ratelimit-reset'));\n const retryAfter = optionalInteger(headers.get('retry-after'));\n if (\n limit === undefined &&\n remaining === undefined &&\n used === undefined &&\n reset === undefined &&\n retryAfter === undefined\n ) {\n return undefined;\n }\n return {\n limit,\n remaining,\n used,\n resetAt: reset === undefined ? undefined : new Date(reset * 1_000),\n retryAfterMs:\n retryAfter === undefined ? undefined : Math.max(0, retryAfter * 1_000),\n };\n}\n\nfunction errorCode(status: number, rateLimit?: ForgeRateLimit): ForgeErrorCode {\n if (status === 401) return 'AUTHENTICATION_FAILED';\n if (status === 404) return 'NOT_FOUND';\n if (status === 422) return 'INVALID_INPUT';\n if (\n status === 429 ||\n (status === 403 &&\n (rateLimit?.remaining === 0 || rateLimit?.retryAfterMs !== undefined))\n ) {\n return 'RATE_LIMITED';\n }\n return 'PROVIDER_ERROR';\n}\n\nexport class GitHubTransport implements ForgeTransport {\n private readonly token: GitHubTokenSource;\n private readonly baseUrl: string;\n private readonly fetchImplementation: typeof globalThis.fetch;\n\n /**\n * Creates a GitHub REST transport with fixed or lazy credentials.\n * @param options Token source, provider URL, and fetch override.\n */\n constructor(options: GitHubTransportOptions) {\n this.token = options.token;\n this.baseUrl = (options.baseUrl ?? 'https://api.github.com').replace(\n /\\/+$/,\n '',\n );\n this.fetchImplementation = options.fetch ?? globalThis.fetch;\n }\n\n /**\n * Executes one GitHub REST request.\n * @param request Method, provider-relative path, body, headers, and signal.\n * @returns Parsed data and metadata for this exact request.\n * @throws {ForgeError} For transport, authentication, rate, or provider failures.\n */\n async request<T>(request: ForgeTransportRequest): Promise<ForgeResponse<T>> {\n const token =\n typeof this.token === 'function' ? await this.token() : this.token;\n let response: Response;\n try {\n response = await this.fetchImplementation(\n `${this.baseUrl}${request.path}`,\n {\n method: request.method,\n headers: {\n Accept: 'application/vnd.github+json',\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n 'X-GitHub-Api-Version': '2022-11-28',\n ...request.headers,\n },\n body:\n request.body === undefined\n ? undefined\n : JSON.stringify(request.body),\n signal: request.signal,\n },\n );\n } catch (cause) {\n throw new ForgeError(\n 'GitHub transport request failed',\n 'TRANSPORT_ERROR',\n {\n cause,\n provider: 'github',\n retryable: true,\n },\n );\n }\n\n const requestId = response.headers.get('x-github-request-id') ?? undefined;\n const rateLimit = responseRateLimit(response.headers);\n const metadata = {\n provider: 'github' as const,\n requestId,\n status: response.status,\n rateLimit,\n };\n let text: string;\n try {\n text = response.status === 204 ? '' : await response.text();\n } catch (cause) {\n throw new ForgeError(\n 'GitHub transport response body failed',\n 'TRANSPORT_ERROR',\n {\n cause,\n provider: 'github',\n status: response.status,\n requestId,\n rateLimit,\n retryable: true,\n },\n );\n }\n let data: unknown;\n try {\n data = text === '' ? undefined : JSON.parse(text);\n } catch {\n data = text;\n }\n\n if (!response.ok) {\n const code = errorCode(response.status, rateLimit);\n const providerMessage =\n typeof data === 'object' &&\n data !== null &&\n 'message' in data &&\n typeof data.message === 'string'\n ? data.message\n : response.statusText;\n throw new ForgeError(`GitHub API error: ${providerMessage}`, code, {\n provider: 'github',\n status: response.status,\n requestId,\n rateLimit,\n details: data,\n retryable: code === 'RATE_LIMITED' || response.status >= 500,\n });\n }\n\n return { data: data as T, metadata };\n }\n}\n","import { createSign } from 'node:crypto';\nimport { ForgeError } from '../forge/errors.js';\nimport type {\n ForgeInstallationRef,\n ForgeRepositoryRef,\n} from '../forge/types.js';\nimport { GitHubForgeProvider } from './forge.js';\nimport { GitHubTransport } from './transport.js';\n\n/** Credentials required to sign GitHub App JSON Web Tokens. */\nexport interface GitHubAppCredentials {\n appId: string | number;\n privateKey: string;\n}\n\n/** Construction options for one request/job-scoped GitHub App authority. */\nexport interface GitHubAppAuthOptions extends GitHubAppCredentials {\n baseUrl?: string;\n fetch?: typeof globalThis.fetch;\n now?: () => Date;\n /** Refresh before provider expiry. Defaults to 60 seconds. */\n expirySkewMs?: number;\n}\n\n/** Installation and repository boundary requested by a caller. */\nexport interface GitHubInstallationScope {\n installationId: string | number;\n owner: string;\n repo: string;\n}\n\n/** Authorized repository client and explicit token-revocation handle. */\nexport interface GitHubInstallationContext {\n installation: ForgeInstallationRef;\n repository: ForgeRepositoryRef;\n forge: GitHubForgeProvider;\n /** Revokes issued tokens remotely and closes this local context. */\n revoke(): Promise<void>;\n}\n\ninterface CachedToken {\n token: string;\n expiresAt: number;\n generation: number;\n authorizedRepositories: Set<string>;\n}\n\nfunction base64UrlJson(value: unknown): string {\n return Buffer.from(JSON.stringify(value)).toString('base64url');\n}\n\n/**\n * Creates a short-lived GitHub App JWT without mutating process credentials.\n * @param credentials GitHub App ID and RSA private key.\n * @param now Clock value used for issued-at and expiry claims.\n * @returns Signed RS256 GitHub App JWT.\n * @throws {ForgeError} When credentials are missing or the key cannot sign.\n */\nexport function createGitHubAppJwt(\n credentials: GitHubAppCredentials,\n now = new Date(),\n): string {\n if (!credentials.appId || !credentials.privateKey) {\n throw new ForgeError(\n 'GitHub App id and private key are required',\n 'CONFIGURATION_ERROR',\n { provider: 'github' },\n );\n }\n const issuedAt = Math.floor(now.getTime() / 1_000) - 60;\n const header = base64UrlJson({ alg: 'RS256', typ: 'JWT' });\n const payload = base64UrlJson({\n iat: issuedAt,\n exp: issuedAt + 10 * 60,\n iss: String(credentials.appId),\n });\n const unsigned = `${header}.${payload}`;\n try {\n const signer = createSign('RSA-SHA256');\n signer.update(unsigned);\n signer.end();\n return `${unsigned}.${signer.sign(credentials.privateKey, 'base64url')}`;\n } catch (cause) {\n throw new ForgeError(\n 'GitHub App private key could not sign a JWT',\n 'CONFIGURATION_ERROR',\n { cause, provider: 'github' },\n );\n }\n}\n\n/**\n * Request/job-scoped GitHub App authority.\n *\n * Keep this object inside a single request or job. Its token cache and in-flight\n * acquisitions are instance fields, so installations cannot share credentials.\n */\nexport class GitHubAppAuth {\n private readonly credentials: GitHubAppCredentials;\n private readonly baseUrl?: string;\n private readonly fetchImplementation?: typeof globalThis.fetch;\n private readonly now: () => Date;\n private readonly expirySkewMs: number;\n private readonly tokens = new Map<string, CachedToken>();\n private readonly issuedTokens = new Map<string, Map<string, number>>();\n private readonly tokenRequests = new Map<string, Promise<CachedToken>>();\n private readonly authorizationRequests = new Map<string, Promise<void>>();\n private readonly revokedInstallations = new Set<string>();\n private nextTokenGeneration = 1;\n\n /**\n * Creates isolated GitHub App authority from credentials and dependencies.\n * @param options Credentials, clock, provider URL, and fetch override.\n */\n constructor(options: GitHubAppAuthOptions) {\n this.credentials = {\n appId: options.appId,\n privateKey: options.privateKey,\n };\n this.baseUrl = options.baseUrl;\n this.fetchImplementation = options.fetch;\n this.now = options.now ?? (() => new Date());\n this.expirySkewMs = options.expirySkewMs ?? 60_000;\n }\n\n /**\n * Clears locally cached credentials without remote revocation.\n * @param installationId Optional installation to clear; omitted clears all.\n * @returns Nothing.\n */\n clear(installationId?: string | number): void {\n if (installationId === undefined) {\n this.tokens.clear();\n this.issuedTokens.clear();\n this.tokenRequests.clear();\n this.authorizationRequests.clear();\n this.revokedInstallations.clear();\n return;\n }\n const id = String(installationId);\n this.clearCachedInstallation(id);\n this.revokedInstallations.delete(id);\n }\n\n /**\n * Acquires and verifies one installation/repository boundary.\n * @param scope Installation ID and exact repository coordinates.\n * @returns An isolated forge provider and revocation handle.\n * @throws {ForgeError} When authentication, provider access, or scope fails.\n */\n async createInstallationContext(\n scope: GitHubInstallationScope,\n ): Promise<GitHubInstallationContext> {\n const installationId = String(scope.installationId);\n const fullName = `${scope.owner}/${scope.repo}`.toLowerCase();\n await this.getAuthorizedToken(installationId, fullName);\n let active = true;\n let revocationInFlight: Promise<void> | undefined;\n const token = () => {\n if (!active) {\n throw new ForgeError(\n 'GitHub installation context has been revoked',\n 'AUTHENTICATION_FAILED',\n { provider: 'github' },\n );\n }\n return this.getAuthorizedToken(installationId, fullName);\n };\n const forge = new GitHubForgeProvider({\n owner: scope.owner,\n repo: scope.repo,\n transport: new GitHubTransport({\n token,\n baseUrl: this.baseUrl,\n fetch: this.fetchImplementation,\n }),\n });\n return {\n installation: { id: installationId },\n repository: {\n owner: scope.owner,\n name: scope.repo,\n fullName: `${scope.owner}/${scope.repo}`,\n },\n forge,\n revoke: async () => {\n active = false;\n if (!revocationInFlight) {\n revocationInFlight = this.revokeInstallationTokens(\n installationId,\n ).finally(() => {\n revocationInFlight = undefined;\n });\n }\n await revocationInFlight;\n },\n };\n }\n\n private async getAuthorizedToken(\n installationId: string,\n fullName: string,\n ): Promise<string> {\n if (this.revokedInstallations.has(installationId)) {\n throw new ForgeError(\n 'GitHub App installation authority has been revoked',\n 'AUTHENTICATION_FAILED',\n { provider: 'github' },\n );\n }\n const cached = await this.getInstallationToken(installationId);\n if (this.revokedInstallations.has(installationId)) {\n throw new ForgeError(\n 'GitHub App installation authority has been revoked',\n 'AUTHENTICATION_FAILED',\n { provider: 'github' },\n );\n }\n if (cached.authorizedRepositories.has(fullName)) return cached.token;\n\n const key = `${installationId}:${cached.generation}:${fullName}`;\n let pending = this.authorizationRequests.get(key);\n if (!pending) {\n pending = this.verifyRepositoryScope(cached, fullName).finally(() => {\n this.authorizationRequests.delete(key);\n });\n this.authorizationRequests.set(key, pending);\n }\n await pending;\n if (this.revokedInstallations.has(installationId)) {\n throw new ForgeError(\n 'GitHub App installation authority has been revoked',\n 'AUTHENTICATION_FAILED',\n { provider: 'github' },\n );\n }\n return cached.token;\n }\n\n private async getInstallationToken(\n installationId: string,\n ): Promise<CachedToken> {\n const cached = this.tokens.get(installationId);\n if (cached && cached.expiresAt - this.expirySkewMs > this.now().getTime()) {\n return cached;\n }\n\n let pending = this.tokenRequests.get(installationId);\n if (!pending) {\n pending = this.acquireInstallationToken(installationId).finally(() => {\n this.tokenRequests.delete(installationId);\n });\n this.tokenRequests.set(installationId, pending);\n }\n return pending;\n }\n\n private async acquireInstallationToken(\n installationId: string,\n ): Promise<CachedToken> {\n const appTransport = new GitHubTransport({\n token: () => createGitHubAppJwt(this.credentials, this.now()),\n baseUrl: this.baseUrl,\n fetch: this.fetchImplementation,\n });\n const response = await appTransport.request<{\n token?: string;\n expires_at?: string;\n }>({\n method: 'POST',\n path: `/app/installations/${encodeURIComponent(installationId)}/access_tokens`,\n });\n const token = response.data.token;\n const expiresAt = Date.parse(response.data.expires_at ?? '');\n if (!token || !Number.isFinite(expiresAt)) {\n throw new ForgeError(\n 'GitHub returned an invalid installation token',\n 'AUTHENTICATION_FAILED',\n { provider: 'github', requestId: response.metadata.requestId },\n );\n }\n const cached: CachedToken = {\n token,\n expiresAt,\n generation: this.nextTokenGeneration,\n authorizedRepositories: new Set(),\n };\n this.nextTokenGeneration += 1;\n const issued = this.issuedTokens.get(installationId) ?? new Map();\n for (const [issuedToken, issuedExpiry] of issued) {\n if (issuedExpiry <= this.now().getTime()) issued.delete(issuedToken);\n }\n issued.set(token, expiresAt);\n this.issuedTokens.set(installationId, issued);\n if (this.revokedInstallations.has(installationId)) {\n try {\n await this.revokeToken(token);\n issued.delete(token);\n } catch (cause) {\n const providerError = cause instanceof ForgeError ? cause : undefined;\n throw new ForgeError(\n 'A GitHub token acquired during revocation could not be revoked',\n 'PROVIDER_ERROR',\n {\n cause,\n provider: 'github',\n status: providerError?.status,\n requestId: providerError?.requestId,\n rateLimit: providerError?.rateLimit,\n retryable: providerError?.retryable,\n },\n );\n }\n throw new ForgeError(\n 'GitHub App installation authority was revoked during token acquisition',\n 'AUTHENTICATION_FAILED',\n { provider: 'github' },\n );\n }\n this.tokens.set(installationId, cached);\n return cached;\n }\n\n private async verifyRepositoryScope(\n cached: CachedToken,\n fullName: string,\n ): Promise<void> {\n const transport = new GitHubTransport({\n token: cached.token,\n baseUrl: this.baseUrl,\n fetch: this.fetchImplementation,\n });\n const separator = fullName.indexOf('/');\n const owner = fullName.slice(0, separator);\n const repo = fullName.slice(separator + 1);\n try {\n await transport.request({\n method: 'GET',\n path: `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`,\n });\n } catch (cause) {\n const providerError = cause instanceof ForgeError ? cause : undefined;\n if (\n providerError?.retryable ||\n providerError?.code === 'AUTHENTICATION_FAILED' ||\n providerError?.code === 'TRANSPORT_ERROR' ||\n (providerError?.status !== 403 && providerError?.status !== 404)\n ) {\n throw cause;\n }\n throw new ForgeError(\n `GitHub App installation is not authorized for ${fullName}`,\n 'AUTHORITY_MISMATCH',\n {\n cause,\n provider: 'github',\n status: providerError?.status,\n requestId: providerError?.requestId,\n rateLimit: providerError?.rateLimit,\n },\n );\n }\n cached.authorizedRepositories.add(fullName);\n }\n\n private async revokeInstallationTokens(\n installationId: string,\n ): Promise<void> {\n this.revokedInstallations.add(installationId);\n const issued = [...(this.issuedTokens.get(installationId)?.keys() ?? [])];\n this.clearCachedInstallation(installationId, false);\n if (issued.length === 0) return;\n\n const retained = this.issuedTokens.get(installationId) ?? new Map();\n const failures: unknown[] = [];\n for (const token of issued) {\n try {\n await this.revokeToken(token);\n retained.delete(token);\n } catch (error) {\n failures.push(error);\n }\n }\n if (retained.size === 0) this.issuedTokens.delete(installationId);\n else this.issuedTokens.set(installationId, retained);\n if (failures.length > 0) {\n const failure = failures[0];\n const providerError = failure instanceof ForgeError ? failure : undefined;\n throw new ForgeError(\n 'One or more GitHub installation tokens could not be revoked',\n 'PROVIDER_ERROR',\n {\n cause: failure,\n provider: 'github',\n status: providerError?.status,\n requestId: providerError?.requestId,\n rateLimit: providerError?.rateLimit,\n retryable: providerError?.retryable,\n },\n );\n }\n }\n\n private async revokeToken(token: string): Promise<void> {\n const transport = new GitHubTransport({\n token,\n baseUrl: this.baseUrl,\n fetch: this.fetchImplementation,\n });\n await transport.request<void>({\n method: 'DELETE',\n path: '/installation/token',\n });\n }\n\n private clearCachedInstallation(\n installationId: string,\n clearIssued = true,\n ): void {\n this.tokens.delete(installationId);\n if (clearIssued) this.issuedTokens.delete(installationId);\n this.tokenRequests.delete(installationId);\n for (const key of this.authorizationRequests.keys()) {\n if (key.startsWith(`${installationId}:`)) {\n this.authorizationRequests.delete(key);\n }\n }\n }\n}\n","import { createHmac } from 'node:crypto';\nimport type { GitHubWebhookHeaders } from './webhooks.js';\n\n/** Exact webhook bytes and headers suitable for deterministic tests. */\nexport interface GitHubWebhookFixture {\n rawBody: Uint8Array;\n headers: GitHubWebhookHeaders;\n}\n\n/**\n * Produces exact, repeatable webhook bytes and headers for integration suites.\n * Pass the same delivery id for duplicates, or a new id with the same payload\n * for a provider redelivery.\n * @param options Secret, delivery identity, event name, and payload.\n * @returns Exact bytes and matching GitHub delivery headers.\n */\nexport function createGitHubWebhookFixture(options: {\n secret: string;\n deliveryId: string;\n event: string;\n payload: unknown;\n}): GitHubWebhookFixture {\n const rawBody = new TextEncoder().encode(JSON.stringify(options.payload));\n const signature = createHmac('sha256', options.secret)\n .update(rawBody)\n .digest('hex');\n return {\n rawBody,\n headers: {\n 'x-github-delivery': options.deliveryId,\n 'x-github-event': options.event,\n 'x-hub-signature-256': `sha256=${signature}`,\n },\n };\n}\n","/**\n * GitHub REST API client\n */\n\nimport { RepositoryError } from '../errors.js';\n\nexport interface GitHubRestConfig {\n token: string;\n baseUrl?: string;\n}\n\n/**\n * GitHub REST API client\n */\nexport class GitHubRest {\n private token: string;\n private baseUrl: string;\n\n constructor(config: GitHubRestConfig) {\n this.token = config.token;\n this.baseUrl = config.baseUrl || 'https://api.github.com';\n }\n\n /**\n * Make a REST API request\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<unknown> {\n const url = `${this.baseUrl}${path}`;\n const headers = {\n Authorization: `Bearer ${this.token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'Content-Type': 'application/json',\n };\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw RepositoryError.fromHTTPStatus(\n response.status,\n `GitHub API error: ${response.statusText}\\n${error}`,\n error,\n );\n }\n\n return response.json();\n }\n\n /**\n * GET request\n */\n async get(path: string): Promise<unknown> {\n return this.request('GET', path);\n }\n\n /**\n * POST request\n */\n async post(path: string, body: unknown): Promise<unknown> {\n return this.request('POST', path, body);\n }\n\n /**\n * PATCH request\n */\n async patch(path: string, body: unknown): Promise<unknown> {\n return this.request('PATCH', path, body);\n }\n\n /**\n * PUT request\n */\n async put(path: string, body?: unknown): Promise<unknown> {\n return this.request('PUT', path, body);\n }\n\n /**\n * DELETE request\n */\n async delete(path: string): Promise<void> {\n await this.request('DELETE', path);\n }\n}\n","/**\n * GitHub repository implementation\n */\n\nimport { GraphQLClient, type IGraphQLClient } from '@happyvertical/graphql';\nimport type {\n CheckRun,\n CommitStatus,\n CreateCheckRunInput,\n CreateCommitStatusInput,\n UpdateCheckRunInput,\n} from '../forge/types.js';\nimport type {\n Branch,\n Comment,\n CreateFromTemplateOptions,\n CreateIssueInput,\n CreatePRInput,\n IRepository,\n Issue,\n Label,\n MergeMethod,\n PullRequest,\n Repository,\n RepositoryConfig,\n SearchFilters,\n UpdateIssueInput,\n} from '../types.js';\nimport { GitHubRest } from './rest.js';\n\n/**\n * GitHub repository implementation\n */\nexport class GitHubRepository implements IRepository {\n private rest: GitHubRest;\n private graphql: IGraphQLClient;\n private owner: string;\n private repo: string;\n\n constructor(config: RepositoryConfig) {\n if (config.type !== 'github') {\n throw new Error('Invalid config type for GitHubRepository');\n }\n\n this.owner = config.owner;\n this.repo = config.repo;\n this.rest = new GitHubRest({\n token: config.token,\n baseUrl: config.baseUrl,\n });\n this.graphql = new GraphQLClient({\n endpoint: config.baseUrl\n ? `${config.baseUrl}/graphql`\n : 'https://api.github.com/graphql',\n token: config.token,\n });\n }\n\n // Repository Info\n async getRepository(): Promise<Repository> {\n const data = (await this.rest.get(`/repos/${this.owner}/${this.repo}`)) as {\n name: string;\n owner: { login: string };\n description: string;\n default_branch: string;\n html_url: string;\n private: boolean;\n };\n\n return {\n owner: data.owner.login,\n name: data.name,\n description: data.description,\n defaultBranch: data.default_branch,\n url: data.html_url,\n isPrivate: data.private,\n };\n }\n\n // Issues\n async getIssue(number: number): Promise<Issue> {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/issues/${number}`,\n )) as {\n number: number;\n node_id: string;\n title: string;\n body: string | null;\n state: string;\n labels: Array<{ name: string; color: string; description: string }>;\n assignees: Array<{ login: string; id: number; type: string }>;\n user: { login: string; id: number; type: string };\n created_at: string;\n updated_at: string;\n closed_at: string | null;\n html_url: string;\n comments: number;\n };\n\n return {\n number: data.number,\n id: data.node_id,\n title: data.title,\n body: data.body || '',\n state: data.state === 'open' ? 'open' : 'closed',\n labels: data.labels.map((l) => ({\n name: l.name,\n color: l.color,\n description: l.description,\n })),\n assignees: data.assignees.map((a) => ({\n login: a.login,\n id: String(a.id),\n type: a.type === 'Bot' ? 'Bot' : 'User',\n })),\n author: {\n login: data.user.login,\n id: String(data.user.id),\n type: data.user.type === 'Bot' ? 'Bot' : 'User',\n },\n createdAt: new Date(data.created_at),\n updatedAt: new Date(data.updated_at),\n closedAt: data.closed_at ? new Date(data.closed_at) : undefined,\n url: data.html_url,\n commentsCount: data.comments,\n };\n }\n\n async createIssue(data: CreateIssueInput): Promise<Issue> {\n const result = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/issues`,\n data,\n )) as ReturnType<typeof this.getIssue> extends Promise<infer T> ? T : never;\n return this.getIssue(result.number);\n }\n\n async updateIssue(number: number, data: UpdateIssueInput): Promise<Issue> {\n await this.rest.patch(\n `/repos/${this.owner}/${this.repo}/issues/${number}`,\n data,\n );\n return this.getIssue(number);\n }\n\n async closeIssue(number: number): Promise<void> {\n await this.updateIssue(number, { state: 'closed' });\n }\n\n // Labels\n async addLabels(issueNumber: number, labels: string[]): Promise<void> {\n await this.rest.post(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/labels`,\n { labels },\n );\n }\n\n async removeLabel(issueNumber: number, label: string): Promise<void> {\n const encodedLabel = encodeURIComponent(label);\n await this.rest.delete(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/labels/${encodedLabel}`,\n );\n }\n\n async createLabel(label: Label): Promise<void> {\n await this.rest.post(`/repos/${this.owner}/${this.repo}/labels`, label);\n }\n\n async updateLabel(name: string, label: Label): Promise<void> {\n await this.rest.patch(\n `/repos/${this.owner}/${this.repo}/labels/${encodeURIComponent(name)}`,\n label,\n );\n }\n\n async listLabels(): Promise<Label[]> {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/labels`,\n )) as Array<{ name: string; color: string; description: string }>;\n\n return data.map((l) => ({\n name: l.name,\n color: l.color,\n description: l.description,\n }));\n }\n\n // Comments\n async addComment(issueNumber: number, body: string): Promise<Comment> {\n const data = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/comments`,\n { body },\n )) as {\n id: number;\n body: string;\n user: { login: string; id: number; type: string };\n created_at: string;\n updated_at: string;\n html_url: string;\n };\n\n return {\n id: String(data.id),\n body: data.body,\n author: {\n login: data.user.login,\n id: String(data.user.id),\n type: data.user.type === 'Bot' ? 'Bot' : 'User',\n },\n createdAt: new Date(data.created_at),\n updatedAt: new Date(data.updated_at),\n url: data.html_url,\n };\n }\n\n async updateComment(commentId: string, body: string): Promise<Comment> {\n const data = (await this.rest.patch(\n `/repos/${this.owner}/${this.repo}/issues/comments/${commentId}`,\n { body },\n )) as ReturnType<typeof this.addComment> extends Promise<infer T>\n ? T\n : never;\n return data as Comment;\n }\n\n async deleteComment(commentId: string): Promise<void> {\n await this.rest.delete(\n `/repos/${this.owner}/${this.repo}/issues/comments/${commentId}`,\n );\n }\n\n async listComments(issueNumber: number): Promise<Comment[]> {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/comments`,\n )) as Array<{\n id: number;\n body: string;\n user: { login: string; id: number; type: string };\n created_at: string;\n updated_at: string;\n html_url: string;\n }>;\n\n return data.map((c) => ({\n id: String(c.id),\n body: c.body,\n author: {\n login: c.user.login,\n id: String(c.user.id),\n type: c.user.type === 'Bot' ? 'Bot' : 'User',\n },\n createdAt: new Date(c.created_at),\n updatedAt: new Date(c.updated_at),\n url: c.html_url,\n }));\n }\n\n // Assignments\n async assignIssue(issueNumber: number, assignees: string[]): Promise<void> {\n await this.rest.post(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/assignees`,\n { assignees },\n );\n }\n\n async unassignIssue(issueNumber: number, assignees: string[]): Promise<void> {\n await this.rest.delete(\n `/repos/${this.owner}/${this.repo}/issues/${issueNumber}/assignees`,\n );\n }\n\n // Pull Requests\n async getPullRequest(number: number): Promise<PullRequest> {\n const issue = await this.getIssue(number);\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/pulls/${number}`,\n )) as {\n head: { ref: string };\n base: { ref: string };\n merged: boolean;\n merged_at: string | null;\n mergeable: boolean;\n draft: boolean;\n };\n\n return {\n ...issue,\n headRef: data.head.ref,\n baseRef: data.base.ref,\n merged: data.merged,\n mergedAt: data.merged_at ? new Date(data.merged_at) : undefined,\n mergeable: data.mergeable,\n draft: data.draft,\n };\n }\n\n async createPullRequest(data: CreatePRInput): Promise<PullRequest> {\n const result = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/pulls`,\n {\n title: data.title,\n body: data.body,\n head: data.headRef,\n base: data.baseRef,\n draft: data.draft,\n },\n )) as { number: number };\n return this.getPullRequest(result.number);\n }\n\n async mergePullRequest(number: number, method?: MergeMethod): Promise<void> {\n await this.rest.put(\n `/repos/${this.owner}/${this.repo}/pulls/${number}/merge`,\n {\n merge_method: method || 'merge',\n },\n );\n }\n\n // Search\n async searchIssues(query: string, filters?: SearchFilters): Promise<Issue[]> {\n let searchQuery = `${query} repo:${this.owner}/${this.repo}`;\n\n if (filters?.state) {\n searchQuery += ` state:${filters.state}`;\n }\n if (filters?.labels) {\n searchQuery += ` ${filters.labels.map((l) => `label:\"${l}\"`).join(' ')}`;\n }\n if (filters?.author) {\n searchQuery += ` author:${filters.author}`;\n }\n if (filters?.assignee) {\n searchQuery += ` assignee:${filters.assignee}`;\n }\n\n const params = new URLSearchParams({\n q: searchQuery,\n sort: filters?.sort || 'created',\n order: filters?.order || 'desc',\n per_page: String(filters?.limit || 30),\n });\n\n const data = (await this.rest.get(`/search/issues?${params}`)) as {\n items: Array<{\n number: number;\n }>;\n };\n\n return Promise.all(data.items.map((item) => this.getIssue(item.number)));\n }\n\n // Node ID resolution\n async getIssueNodeId(issueNumber: number): Promise<string> {\n const issue = await this.getIssue(issueNumber);\n return issue.id;\n }\n\n async getPRNodeId(prNumber: number): Promise<string> {\n const pr = await this.getPullRequest(prNumber);\n return pr.id;\n }\n\n // Branch Management\n async createBranch(name: string, fromRef: string): Promise<Branch> {\n // First get the SHA for the reference\n const refData = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/git/ref/heads/${fromRef}`,\n )) as { object: { sha: string } };\n\n // Create the new branch\n await this.rest.post(`/repos/${this.owner}/${this.repo}/git/refs`, {\n ref: `refs/heads/${name}`,\n sha: refData.object.sha,\n });\n\n return {\n name,\n sha: refData.object.sha,\n protected: false,\n };\n }\n\n async deleteBranch(name: string): Promise<void> {\n await this.rest.delete(\n `/repos/${this.owner}/${this.repo}/git/refs/heads/${name}`,\n );\n }\n\n async getBranch(name: string): Promise<Branch | null> {\n try {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/branches/${encodeURIComponent(name)}`,\n )) as {\n name: string;\n commit: { sha: string };\n protected: boolean;\n };\n\n return {\n name: data.name,\n sha: data.commit.sha,\n protected: data.protected,\n };\n } catch (error) {\n // Return null if branch not found (404)\n if (\n error instanceof Error &&\n 'code' in error &&\n (error as { code: string }).code === 'NOT_FOUND'\n ) {\n return null;\n }\n throw error;\n }\n }\n\n // PR Draft/Review\n async markPRReady(prNumber: number): Promise<void> {\n const pr = await this.getPullRequest(prNumber);\n const mutation = `\n mutation($pullRequestId: ID!) {\n markPullRequestReadyForReview(input: {\n pullRequestId: $pullRequestId\n }) {\n pullRequest {\n id\n }\n }\n }\n `;\n await this.graphql.mutate(mutation, { pullRequestId: pr.id });\n }\n\n async convertPRToDraft(prNumber: number): Promise<void> {\n const pr = await this.getPullRequest(prNumber);\n const mutation = `\n mutation($pullRequestId: ID!) {\n convertPullRequestToDraft(input: {\n pullRequestId: $pullRequestId\n }) {\n pullRequest {\n id\n }\n }\n }\n `;\n await this.graphql.mutate(mutation, { pullRequestId: pr.id });\n }\n\n async requestReview(prNumber: number, reviewers: string[]): Promise<void> {\n await this.rest.post(\n `/repos/${this.owner}/${this.repo}/pulls/${prNumber}/requested_reviewers`,\n { reviewers },\n );\n }\n\n // Workflow\n async triggerWorkflow(\n workflowId: string,\n ref: string,\n inputs?: Record<string, string>,\n ): Promise<void> {\n await this.rest.post(\n `/repos/${this.owner}/${this.repo}/actions/workflows/${workflowId}/dispatches`,\n { ref, inputs: inputs || {} },\n );\n }\n\n // Linking\n async findPRsForIssue(issueNumber: number): Promise<PullRequest[]> {\n // Search for PRs that reference this issue with closing keywords\n const keywords = ['closes', 'fixes', 'resolves'];\n const searchTerms = keywords\n .map((k) => `${k} #${issueNumber}`)\n .join(' OR ');\n const query = `is:pr repo:${this.owner}/${this.repo} ${searchTerms}`;\n\n const data = (await this.rest.get(\n `/search/issues?q=${encodeURIComponent(query)}`,\n )) as {\n items: Array<{ number: number }>;\n };\n\n return Promise.all(\n data.items.map((item) => this.getPullRequest(item.number)),\n );\n }\n\n async findIssueForPR(prNumber: number): Promise<Issue | null> {\n const pr = await this.getPullRequest(prNumber);\n\n // Look for closing keywords in PR body\n const closingPattern = /(?:closes?|fixes?|resolves?)\\s+#(\\d+)/gi;\n const matches = [...pr.body.matchAll(closingPattern)];\n\n if (matches.length === 0) {\n return null;\n }\n\n // Return the first linked issue\n const issueNumber = Number.parseInt(matches[0][1], 10);\n try {\n return await this.getIssue(issueNumber);\n } catch {\n return null;\n }\n }\n\n // File Content\n async getFileContent(path: string, ref?: string): Promise<string | null> {\n try {\n const url = `/repos/${this.owner}/${this.repo}/contents/${path}${ref ? `?ref=${ref}` : ''}`;\n const data = (await this.rest.get(url)) as {\n type: string;\n content?: string;\n encoding?: string;\n };\n\n if (data.type !== 'file' || !data.content) {\n return null;\n }\n\n // GitHub returns base64-encoded content\n if (data.encoding === 'base64') {\n return Buffer.from(data.content, 'base64').toString('utf-8');\n }\n\n return data.content;\n } catch {\n // 404 means file doesn't exist\n return null;\n }\n }\n\n async listDirectoryFiles(path: string, ref?: string): Promise<string[]> {\n try {\n const url = `/repos/${this.owner}/${this.repo}/contents/${path}${ref ? `?ref=${ref}` : ''}`;\n const data = (await this.rest.get(url)) as Array<{\n name: string;\n type: string;\n }>;\n\n if (!Array.isArray(data)) {\n return [];\n }\n\n return data\n .filter((item) => item.type === 'file')\n .map((item) => item.name);\n } catch {\n // 404 means directory doesn't exist\n return [];\n }\n }\n\n /**\n * Publishes one GitHub commit status.\n * @param input Exact commit SHA and status attributes.\n * @returns Normalized published status.\n */\n async createCommitStatus(\n input: CreateCommitStatusInput,\n ): Promise<CommitStatus> {\n const data = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/statuses/${encodeURIComponent(input.sha)}`,\n {\n state: input.state,\n context: input.context,\n description: input.description,\n target_url: input.targetUrl,\n },\n )) as Record<string, unknown>;\n return this.mapCommitStatus(data);\n }\n\n /**\n * Returns complete commit-status history across GitHub pages.\n * @param sha Exact commit SHA.\n * @returns Every normalized status for the commit.\n */\n async listCommitStatuses(sha: string): Promise<readonly CommitStatus[]> {\n const statuses: CommitStatus[] = [];\n let page = 1;\n while (true) {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/commits/${encodeURIComponent(sha)}/statuses?per_page=100&page=${page}`,\n )) as Record<string, unknown>[];\n statuses.push(...data.map((status) => this.mapCommitStatus(status)));\n if (data.length < 100) return statuses;\n page += 1;\n }\n }\n\n /**\n * Publishes one GitHub check run.\n * @param input Check identity, exact head SHA, state, and output.\n * @returns Normalized published check run.\n */\n async createCheckRun(input: CreateCheckRunInput): Promise<CheckRun> {\n const data = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/check-runs`,\n this.mapCheckRunInput(input),\n )) as Record<string, unknown>;\n return this.mapCheckRun(data);\n }\n\n /**\n * Changes one GitHub check run.\n * @param id GitHub check-run ID.\n * @param input Attributes to change.\n * @returns Normalized updated check run.\n */\n async updateCheckRun(\n id: string,\n input: UpdateCheckRunInput,\n ): Promise<CheckRun> {\n const data = (await this.rest.patch(\n `/repos/${this.owner}/${this.repo}/check-runs/${encodeURIComponent(id)}`,\n this.mapCheckRunInput(input),\n )) as Record<string, unknown>;\n return this.mapCheckRun(data);\n }\n\n /**\n * Returns complete GitHub check history, including reruns.\n * @param sha Exact commit SHA.\n * @returns Every normalized check run for the commit.\n */\n async listCheckRuns(sha: string): Promise<readonly CheckRun[]> {\n const checkRuns: CheckRun[] = [];\n let page = 1;\n let totalCount: number | undefined;\n while (true) {\n const data = (await this.rest.get(\n `/repos/${this.owner}/${this.repo}/commits/${encodeURIComponent(sha)}/check-runs?filter=all&per_page=100&page=${page}`,\n )) as {\n check_runs?: Record<string, unknown>[];\n total_count?: number;\n };\n const pageRuns = data.check_runs ?? [];\n totalCount ??= data.total_count;\n checkRuns.push(...pageRuns.map((checkRun) => this.mapCheckRun(checkRun)));\n if (\n pageRuns.length < 100 ||\n (totalCount !== undefined && checkRuns.length >= totalCount)\n ) {\n return checkRuns;\n }\n page += 1;\n }\n }\n\n private mapCommitStatus(data: Record<string, unknown>): CommitStatus {\n return {\n id: String(data.id ?? data.node_id ?? ''),\n sha: String(data.sha ?? ''),\n state: String(data.state ?? ''),\n context: String(data.context ?? ''),\n description:\n typeof data.description === 'string' ? data.description : undefined,\n targetUrl:\n typeof data.target_url === 'string' ? data.target_url : undefined,\n createdAt:\n typeof data.created_at === 'string'\n ? new Date(data.created_at)\n : undefined,\n raw: data,\n };\n }\n\n private mapCheckRunInput(\n input: CreateCheckRunInput | UpdateCheckRunInput,\n ): Record<string, unknown> {\n return {\n ...('name' in input ? { name: input.name } : {}),\n ...('headSha' in input ? { head_sha: input.headSha } : {}),\n status: input.status,\n conclusion: input.conclusion,\n details_url: input.detailsUrl,\n external_id: input.externalId,\n started_at:\n input.startedAt instanceof Date\n ? input.startedAt.toISOString()\n : input.startedAt,\n completed_at:\n input.completedAt instanceof Date\n ? input.completedAt.toISOString()\n : input.completedAt,\n output: input.output,\n };\n }\n\n private mapCheckRun(data: Record<string, unknown>): CheckRun {\n return {\n id: String(data.id ?? data.node_id ?? ''),\n name: String(data.name ?? ''),\n headSha: String(data.head_sha ?? ''),\n status: (data.status ?? 'queued') as CheckRun['status'],\n conclusion:\n typeof data.conclusion === 'string'\n ? (data.conclusion as CheckRun['conclusion'])\n : undefined,\n detailsUrl:\n typeof data.details_url === 'string' ? data.details_url : undefined,\n externalId:\n typeof data.external_id === 'string' ? data.external_id : undefined,\n startedAt:\n typeof data.started_at === 'string'\n ? new Date(data.started_at)\n : undefined,\n completedAt:\n typeof data.completed_at === 'string'\n ? new Date(data.completed_at)\n : undefined,\n raw: data,\n };\n }\n\n // Repository Creation from Template\n\n /**\n * Create a new repository from this repository as a template.\n *\n * Uses the GitHub \"Generate\" API: POST /repos/{template_owner}/{template_repo}/generate\n * The current repository (this.owner/this.repo) is used as the template.\n */\n async createRepositoryFromTemplate(\n options: CreateFromTemplateOptions,\n ): Promise<Repository> {\n const data = (await this.rest.post(\n `/repos/${this.owner}/${this.repo}/generate`,\n {\n owner: options.owner,\n name: options.name,\n description: options.description || '',\n private: options.isPrivate ?? true,\n include_all_branches: options.includeAllBranches ?? false,\n },\n )) as {\n name: string;\n owner: { login: string };\n description: string;\n default_branch: string;\n html_url: string;\n private: boolean;\n };\n\n return {\n owner: data.owner.login,\n name: data.name,\n description: data.description || '',\n defaultBranch: data.default_branch,\n url: data.html_url,\n isPrivate: data.private,\n };\n }\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto';\nimport { ForgeError, ForgeSignatureError } from '../forge/errors.js';\nimport type {\n CheckRun,\n ForgeActor,\n ForgeEventEnvelope,\n ForgeInstallationRef,\n ForgeObservation,\n ForgePullRequestRef,\n ForgeRepositoryRef,\n} from '../forge/types.js';\n\nexport type GitHubWebhookHeaders =\n | Headers\n | Readonly<Record<string, string | readonly string[] | undefined>>;\n\n/** Construction options for raw GitHub webhook verification. */\nexport interface GitHubWebhookVerifierOptions {\n /** Current secret first, followed by still-valid rotation secrets. */\n secrets: string | readonly string[];\n now?: () => Date;\n}\n\nfunction headerValue(\n headers: GitHubWebhookHeaders,\n requestedName: string,\n): string | undefined {\n if (headers instanceof Headers) {\n return headers.get(requestedName) ?? undefined;\n }\n const requested = requestedName.toLowerCase();\n for (const [name, value] of Object.entries(headers)) {\n if (name.toLowerCase() !== requested) continue;\n return typeof value === 'string' ? value : value?.[0];\n }\n return undefined;\n}\n\nfunction object(value: unknown): Record<string, unknown> {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction optionalString(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction actor(value: unknown): ForgeActor | undefined {\n const data = object(value);\n const login = optionalString(data.login);\n if (!login) return undefined;\n return {\n id: data.id === undefined ? undefined : String(data.id),\n login,\n type: optionalString(data.type),\n };\n}\n\nfunction repository(value: unknown): ForgeRepositoryRef | undefined {\n const data = object(value);\n const ownerData = object(data.owner);\n const fullName = optionalString(data.full_name);\n const name = optionalString(data.name);\n const owner = optionalString(ownerData.login);\n if (!name || (!owner && !fullName)) return undefined;\n const resolvedOwner = owner ?? fullName?.split('/')[0] ?? '';\n return {\n id: data.node_id === undefined ? undefined : String(data.node_id),\n owner: resolvedOwner,\n name,\n fullName: fullName ?? `${resolvedOwner}/${name}`,\n defaultBranch: optionalString(data.default_branch),\n private: typeof data.private === 'boolean' ? data.private : undefined,\n url: optionalString(data.html_url),\n };\n}\n\nfunction installation(value: unknown): ForgeInstallationRef | undefined {\n const data = object(value);\n if (data.id === undefined) return undefined;\n const accountData = object(data.account);\n return {\n id: String(data.id),\n account: optionalString(accountData.login),\n repositorySelection:\n data.repository_selection === 'all' ||\n data.repository_selection === 'selected'\n ? data.repository_selection\n : undefined,\n };\n}\n\nfunction pullRequest(value: unknown): ForgePullRequestRef {\n const data = object(value);\n const head = object(data.head);\n const base = object(data.base);\n return {\n id: data.node_id === undefined ? undefined : String(data.node_id),\n number: Number(data.number),\n state: data.state === 'closed' ? 'closed' : 'open',\n draft: typeof data.draft === 'boolean' ? data.draft : undefined,\n headSha: String(head.sha ?? ''),\n headRef: optionalString(head.ref),\n baseSha: optionalString(base.sha),\n baseRef: optionalString(base.ref),\n merged: typeof data.merged === 'boolean' ? data.merged : undefined,\n mergeCommitSha: optionalString(data.merge_commit_sha),\n url: optionalString(data.html_url),\n };\n}\n\nfunction check(value: unknown): CheckRun {\n const data = object(value);\n const app = object(data.app);\n return {\n id: String(data.id ?? data.node_id ?? ''),\n name: String(data.name ?? app.name ?? 'check_suite'),\n headSha: String(data.head_sha ?? ''),\n status: (data.status ?? 'queued') as CheckRun['status'],\n conclusion:\n typeof data.conclusion === 'string'\n ? (data.conclusion as CheckRun['conclusion'])\n : undefined,\n detailsUrl: optionalString(data.details_url),\n externalId: optionalString(data.external_id),\n startedAt: optionalString(data.started_at)\n ? new Date(String(data.started_at))\n : undefined,\n completedAt: optionalString(data.completed_at)\n ? new Date(String(data.completed_at))\n : undefined,\n raw: data,\n };\n}\n\nfunction occurrence(payload: Record<string, unknown>): Date | undefined {\n const candidates = [\n object(payload.review).submitted_at,\n object(payload.check_run).completed_at,\n object(payload.check_run).started_at,\n payload.created_at,\n object(payload.status).created_at,\n object(payload.deployment_status).created_at,\n object(payload.deployment).created_at,\n object(payload.pull_request).updated_at,\n object(payload.head_commit).timestamp,\n ];\n for (const candidate of candidates) {\n if (typeof candidate !== 'string') continue;\n const timestamp = new Date(candidate);\n if (!Number.isNaN(timestamp.getTime())) return timestamp;\n }\n return undefined;\n}\n\nfunction normalizeObservation(\n event: string,\n payload: Record<string, unknown>,\n action?: string,\n): ForgeObservation {\n if (event === 'ping') {\n return {\n kind: 'availability',\n available: true,\n message: optionalString(payload.zen),\n };\n }\n if (event === 'installation' || event === 'installation_repositories') {\n const installationRef = installation(payload.installation);\n if (!installationRef) return { kind: 'unknown' };\n const repositories = [\n ...(Array.isArray(payload.repositories) ? payload.repositories : []),\n ...(Array.isArray(payload.repositories_added)\n ? payload.repositories_added\n : []),\n ...(Array.isArray(payload.repositories_removed)\n ? payload.repositories_removed\n : []),\n ]\n .map(repository)\n .filter((item): item is ForgeRepositoryRef => item !== undefined);\n return {\n kind: 'installation',\n installation: installationRef,\n repositories,\n };\n }\n if (event === 'repository') {\n const repositoryRef = repository(payload.repository);\n return repositoryRef\n ? { kind: 'repository', repository: repositoryRef }\n : { kind: 'unknown' };\n }\n if (event === 'pull_request') {\n const pullRequestRef = pullRequest(payload.pull_request);\n return action === 'closed' && pullRequestRef.merged\n ? {\n kind: 'merge',\n pullRequest: pullRequestRef,\n mergeCommitSha: pullRequestRef.mergeCommitSha,\n }\n : { kind: 'pull_request', pullRequest: pullRequestRef };\n }\n if (event === 'pull_request_review') {\n const review = object(payload.review);\n return {\n kind: 'review',\n pullRequest: pullRequest(payload.pull_request),\n review: {\n id: String(review.id ?? review.node_id ?? ''),\n state: String(review.state ?? ''),\n body: optionalString(review.body),\n commitSha: optionalString(review.commit_id),\n submittedAt: optionalString(review.submitted_at)\n ? new Date(String(review.submitted_at))\n : undefined,\n author: actor(review.user),\n },\n };\n }\n if (event === 'push') {\n return {\n kind: 'push',\n ref: String(payload.ref ?? ''),\n beforeSha: optionalString(payload.before),\n afterSha: String(payload.after ?? ''),\n forced: typeof payload.forced === 'boolean' ? payload.forced : undefined,\n created:\n typeof payload.created === 'boolean' ? payload.created : undefined,\n deleted:\n typeof payload.deleted === 'boolean' ? payload.deleted : undefined,\n };\n }\n if (event === 'status') {\n return {\n kind: 'status',\n status: {\n id: String(payload.id ?? ''),\n sha: String(payload.sha ?? ''),\n state: String(payload.state ?? ''),\n context: String(payload.context ?? ''),\n description: optionalString(payload.description),\n targetUrl: optionalString(payload.target_url),\n createdAt: optionalString(payload.created_at)\n ? new Date(String(payload.created_at))\n : undefined,\n raw: payload,\n },\n };\n }\n if (event === 'check_run' || event === 'check_suite') {\n return {\n kind: 'check',\n check: check(payload.check_run ?? payload.check_suite),\n };\n }\n if (event === 'merge_group') {\n const mergeGroup = object(payload.merge_group);\n return {\n kind: 'merge_group',\n headSha: String(mergeGroup.head_sha ?? ''),\n headRef: optionalString(mergeGroup.head_ref),\n baseSha: optionalString(mergeGroup.base_sha),\n baseRef: optionalString(mergeGroup.base_ref),\n };\n }\n if (event === 'deployment' || event === 'deployment_status') {\n const deployment = object(payload.deployment);\n const deploymentStatus = object(payload.deployment_status);\n return {\n kind: 'deployment',\n deployment: {\n id: String(deployment.id ?? ''),\n sha: optionalString(deployment.sha),\n ref: optionalString(deployment.ref),\n environment:\n optionalString(deploymentStatus.environment) ??\n optionalString(deployment.environment),\n state: optionalString(deploymentStatus.state),\n url:\n optionalString(deploymentStatus.environment_url) ??\n optionalString(deploymentStatus.target_url),\n },\n };\n }\n return { kind: 'unknown' };\n}\n\n/**\n * Normalizes one already-verified GitHub payload.\n * @param deliveryId Stable provider delivery identity.\n * @param event GitHub event header value.\n * @param raw Parsed provider payload.\n * @param receivedAt Local receipt timestamp.\n * @returns A provider-neutral event envelope preserving the parsed payload.\n */\nexport function normalizeGitHubWebhook(\n deliveryId: string,\n event: string,\n raw: unknown,\n receivedAt = new Date(),\n): ForgeEventEnvelope {\n const payload = object(raw);\n const action = optionalString(payload.action);\n return {\n provider: 'github',\n deliveryId,\n event,\n action,\n occurredAt: occurrence(payload),\n receivedAt,\n installation: installation(payload.installation),\n repository: repository(payload.repository),\n actor: actor(payload.sender),\n observation: normalizeObservation(event, payload, action),\n raw,\n };\n}\n\nexport class GitHubWebhookVerifier {\n private readonly secrets: readonly string[];\n private readonly now: () => Date;\n\n /**\n * Creates a verifier with a current secret and optional rotation secrets.\n * @param options Current/rotation secrets and optional clock.\n * @throws {ForgeError} When no non-empty secret is configured.\n */\n constructor(options: GitHubWebhookVerifierOptions) {\n this.secrets =\n typeof options.secrets === 'string'\n ? [options.secrets]\n : [...options.secrets];\n if (this.secrets.length === 0 || this.secrets.some((secret) => !secret)) {\n throw new ForgeError(\n 'At least one non-empty GitHub webhook secret is required',\n 'CONFIGURATION_ERROR',\n { provider: 'github' },\n );\n }\n this.now = options.now ?? (() => new Date());\n }\n\n /**\n * Verifies unchanged provider bytes with constant-time comparisons.\n * @param rawBody Exact bytes received from the HTTP server.\n * @param signature GitHub SHA-256 signature header.\n * @returns Index of the configured secret that matched.\n * @throws {ForgeSignatureError} When the signature is missing or invalid.\n */\n verify(rawBody: Uint8Array, signature: string | undefined): number {\n if (!signature?.startsWith('sha256=')) throw new ForgeSignatureError();\n const suppliedHex = signature.slice('sha256='.length);\n if (!/^[a-fA-F0-9]{64}$/.test(suppliedHex)) {\n throw new ForgeSignatureError();\n }\n const supplied = Buffer.from(suppliedHex, 'hex');\n let matchedIndex = -1;\n this.secrets.forEach((secret, index) => {\n const expected = createHmac('sha256', secret).update(rawBody).digest();\n if (timingSafeEqual(expected, supplied)) matchedIndex = index;\n });\n if (matchedIndex === -1) throw new ForgeSignatureError();\n return matchedIndex;\n }\n\n /**\n * Verifies raw bytes before decoding and normalizes the delivery.\n * @param rawBody Exact bytes received from the HTTP server.\n * @param headers Case-insensitive GitHub delivery headers.\n * @returns Verified normalized delivery.\n * @throws {ForgeError} For invalid signatures, headers, UTF-8, or JSON.\n */\n verifyAndNormalize(\n rawBody: Uint8Array,\n headers: GitHubWebhookHeaders,\n ): ForgeEventEnvelope {\n this.verify(rawBody, headerValue(headers, 'x-hub-signature-256'));\n const deliveryId = headerValue(headers, 'x-github-delivery');\n const event = headerValue(headers, 'x-github-event');\n if (!deliveryId || !event) {\n throw new ForgeError(\n 'GitHub delivery identity and event headers are required',\n 'INVALID_INPUT',\n { provider: 'github' },\n );\n }\n let payload: unknown;\n try {\n payload = JSON.parse(\n new TextDecoder('utf-8', { fatal: true }).decode(rawBody),\n );\n } catch (cause) {\n throw new ForgeError(\n 'GitHub webhook body is not valid UTF-8 JSON',\n 'INVALID_INPUT',\n { cause, provider: 'github' },\n );\n }\n return normalizeGitHubWebhook(deliveryId, event, payload, this.now());\n }\n}\n","/**\n * Issue body parsing and rendering utilities\n *\n * Parses GitHub issue bodies created from YAML form templates.\n * GitHub renders form fields as markdown sections with ### headings.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport yaml from 'js-yaml';\nimport type { IRepository } from './types.js';\n\n/**\n * Template field definition - mirrors GitHub ISSUE_TEMPLATE YAML structure\n */\nexport interface TemplateField {\n type: 'textarea' | 'input' | 'dropdown' | 'checkboxes' | 'markdown';\n id?: string;\n attributes: {\n label: string;\n description?: string;\n placeholder?: string;\n value?: string;\n options?: string[];\n };\n validations?: {\n required?: boolean;\n };\n}\n\n/**\n * Issue template definition\n */\nexport interface IssueTemplate {\n name: string;\n description?: string;\n title?: string;\n labels?: string[];\n assignees?: string[];\n body: TemplateField[];\n}\n\n/**\n * Load and parse an issue template from a YAML file\n *\n * @param yamlPath - Path to the YAML template file\n * @returns Parsed issue template\n *\n * @example\n * ```typescript\n * const template = await loadIssueTemplate('.github/ISSUE_TEMPLATE/bug_report.yml');\n * ```\n */\nexport async function loadIssueTemplate(\n yamlPath: string,\n): Promise<IssueTemplate> {\n const content = await readFile(yamlPath, 'utf-8');\n return parseIssueTemplate(content);\n}\n\n/**\n * Parse an issue template from YAML content\n *\n * @param yamlContent - YAML content string\n * @returns Parsed issue template\n *\n * @example\n * ```typescript\n * const template = parseIssueTemplate(`\n * name: Bug Report\n * body:\n * - type: textarea\n * id: description\n * attributes:\n * label: Description\n * `);\n * ```\n */\nexport function parseIssueTemplate(yamlContent: string): IssueTemplate {\n const parsed = yaml.load(yamlContent) as IssueTemplate;\n\n if (!parsed.name) {\n throw new Error('Issue template must have a name');\n }\n\n if (!parsed.body || !Array.isArray(parsed.body)) {\n throw new Error('Issue template must have a body array');\n }\n\n return parsed;\n}\n\n/**\n * Parse an issue body into field values\n *\n * GitHub renders form fields as markdown sections:\n * ```\n * ### Label\n *\n * Content here\n *\n * ### Next Label\n * ```\n *\n * Without a template, returns a Record<string, string> keyed by label.\n * With a template, returns a Record<string, string> keyed by field ID.\n *\n * @param body - The issue body markdown\n * @param template - Optional template for mapping labels to field IDs\n * @returns Parsed fields as key-value pairs\n *\n * @example\n * ```typescript\n * // Without template - keyed by label\n * const fields = parseIssueBody(issue.body);\n * // { 'Description': '...', 'Steps to Reproduce': '...' }\n *\n * // With template - keyed by field ID\n * const template = await loadIssueTemplate('.github/ISSUE_TEMPLATE/bug_report.yml');\n * const fields = parseIssueBody(issue.body, template);\n * // { description: '...', reproduction: '...' }\n * ```\n */\nexport function parseIssueBody(\n body: string,\n template?: IssueTemplate,\n): Record<string, string> {\n const sections = parseSections(body);\n\n if (!template) {\n return sections;\n }\n\n // Build label-to-id mapping from template\n const labelToId = new Map<string, string>();\n for (const field of template.body) {\n if (field.id && field.attributes?.label) {\n labelToId.set(field.attributes.label, field.id);\n }\n }\n\n // Map labels to field IDs\n const result: Record<string, string> = {};\n for (const [label, content] of Object.entries(sections)) {\n const id = labelToId.get(label);\n if (id) {\n result[id] = content;\n } else {\n // Keep original label if no ID mapping found\n result[label] = content;\n }\n }\n\n return result;\n}\n\n/**\n * Parse markdown sections (### headers) into key-value pairs\n */\nfunction parseSections(body: string): Record<string, string> {\n const result: Record<string, string> = {};\n\n // Match ### headers and their content\n // Content is everything until the next ### or --- or end of string\n const sectionRegex =\n /^### (.+?)\\r?\\n\\r?\\n([\\s\\S]*?)(?=\\r?\\n### |\\r?\\n---|\\s*$)/gm;\n\n for (const match of body.matchAll(sectionRegex)) {\n const label = match[1].trim();\n const content = match[2].trim();\n result[label] = content;\n }\n\n return result;\n}\n\n/**\n * Render fields into an issue body markdown string\n *\n * Without a template, uses field keys as labels.\n * With a template, uses field IDs to look up labels and renders in template order.\n *\n * @param fields - Field values as key-value pairs\n * @param template - Optional template for field ordering and labels\n * @returns Markdown string for issue body\n *\n * @example\n * ```typescript\n * // Without template\n * const body = renderIssueBody({\n * 'Description': 'Bug description here',\n * 'Steps to Reproduce': '1. Do X\\n2. See error'\n * });\n *\n * // With template\n * const template = await loadIssueTemplate('.github/ISSUE_TEMPLATE/bug_report.yml');\n * const body = renderIssueBody({\n * description: 'Bug description here',\n * reproduction: '1. Do X\\n2. See error'\n * }, template);\n * ```\n */\nexport function renderIssueBody(\n fields: Record<string, string>,\n template?: IssueTemplate,\n): string {\n const sections: string[] = [];\n\n if (!template) {\n // Without template, render in field order\n for (const [label, content] of Object.entries(fields)) {\n sections.push(`### ${label}\\n\\n${content}`);\n }\n } else {\n // With template, render in template order using field IDs\n const idToContent = new Map(Object.entries(fields));\n\n for (const field of template.body) {\n // Skip markdown-only fields (no id)\n if (!field.id || field.type === 'markdown') {\n continue;\n }\n\n const label = field.attributes?.label || field.id;\n const content = idToContent.get(field.id);\n\n if (content !== undefined) {\n sections.push(`### ${label}\\n\\n${content}`);\n }\n }\n }\n\n return sections.join('\\n\\n');\n}\n\n/**\n * Get a specific field value from an issue body\n *\n * @param body - The issue body markdown\n * @param fieldIdOrLabel - Field ID (with template) or label (without template)\n * @param template - Optional template for field ID lookup\n * @returns Field value or undefined if not found\n */\nexport function getIssueField(\n body: string,\n fieldIdOrLabel: string,\n template?: IssueTemplate,\n): string | undefined {\n const fields = parseIssueBody(body, template);\n return fields[fieldIdOrLabel];\n}\n\n/**\n * Update a specific field in an issue body\n *\n * @param body - The issue body markdown\n * @param fieldIdOrLabel - Field ID (with template) or label (without template)\n * @param value - New value for the field\n * @param template - Optional template for field ID lookup\n * @returns Updated issue body markdown\n */\nexport function updateIssueField(\n body: string,\n fieldIdOrLabel: string,\n value: string,\n template?: IssueTemplate,\n): string {\n const fields = parseIssueBody(body, template);\n fields[fieldIdOrLabel] = value;\n return renderIssueBody(fields, template);\n}\n\n/**\n * Fetch issue templates from a repository via GitHub API\n *\n * @param repo - Repository client implementing IRepository\n * @returns Array of parsed issue templates\n *\n * @example\n * ```typescript\n * const repo = await getRepository({ type: 'github', owner: 'org', repo: 'name', token });\n * const templates = await fetchIssueTemplates(repo);\n * // [{ name: 'Bug Report', labels: ['bug'], body: [...] }, ...]\n * ```\n */\nexport async function fetchIssueTemplates(\n repo: IRepository,\n): Promise<IssueTemplate[]> {\n const templatePath = '.github/ISSUE_TEMPLATE';\n const files = await repo.listDirectoryFiles(templatePath);\n const templates: IssueTemplate[] = [];\n\n for (const file of files) {\n if (file.endsWith('.yml') || file.endsWith('.yaml')) {\n const content = await repo.getFileContent(`${templatePath}/${file}`);\n if (content) {\n try {\n templates.push(parseIssueTemplate(content));\n } catch (e) {\n console.warn(`[repos] Failed to parse template ${file}:`, e);\n }\n }\n }\n }\n\n return templates;\n}\n\n/**\n * Detect which template an issue was created from based on labels\n *\n * Matches issue labels against template labels to find the best match.\n * Returns the template with the most matching labels.\n *\n * @param labels - Issue labels\n * @param templates - Available templates\n * @returns Matching template or undefined if no match\n *\n * @example\n * ```typescript\n * const templates = await fetchIssueTemplates(repo);\n * const template = detectTemplateFromLabels(['bug', 'critical'], templates);\n * if (template) {\n * const fields = parseIssueBody(issue.body, template);\n * }\n * ```\n */\nexport function detectTemplateFromLabels(\n labels: string[],\n templates: IssueTemplate[],\n): IssueTemplate | undefined {\n const labelSet = new Set(labels.map((l) => l.toLowerCase()));\n\n let bestMatch: IssueTemplate | undefined;\n let bestScore = 0;\n\n for (const template of templates) {\n if (!template.labels || template.labels.length === 0) continue;\n\n const matchCount = template.labels.filter((l) =>\n labelSet.has(l.toLowerCase()),\n ).length;\n\n // Require at least one matching label\n if (matchCount > 0 && matchCount > bestScore) {\n bestScore = matchCount;\n bestMatch = template;\n }\n }\n\n return bestMatch;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/repos",
3
- "version": "0.83.0",
3
+ "version": "0.85.0",
4
4
  "description": "Standardized repository interface for GitHub, GitLab, Bitbucket, and Azure DevOps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "js-yaml": "^4.1.1",
19
- "@happyvertical/graphql": "0.83.0"
19
+ "@happyvertical/graphql": "0.85.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/js-yaml": "^4.0.9",