@aigne/afs-github 1.11.0-beta.6

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/client.ts","../src/types.ts","../src/github.ts"],"sourcesContent":["/**\n * GitHub API Client\n *\n * Wraps Octokit with throttling, retry, and caching.\n */\n\nimport { retry } from \"@octokit/plugin-retry\";\nimport { throttling } from \"@octokit/plugin-throttling\";\nimport { Octokit } from \"@octokit/rest\";\nimport type { AuthOptions, CacheOptions, RateLimitOptions } from \"./types.js\";\n\n/**\n * Cache entry\n */\ninterface CacheEntry {\n data: unknown;\n expiresAt: number;\n}\n\n/**\n * GitHub Contents API item\n */\nexport interface ContentsItem {\n name: string;\n path: string;\n type: \"file\" | \"dir\" | \"symlink\" | \"submodule\";\n size: number;\n sha: string;\n download_url: string | null;\n /** Base64 encoded content, only for files <1MB */\n content?: string;\n /** Encoding type, typically \"base64\" when content is present */\n encoding?: string;\n}\n\n/**\n * Response from Contents API - can be single item or array\n */\nexport type ContentsResponse = ContentsItem | ContentsItem[];\n\n/**\n * GitHub Branch item\n */\nexport interface BranchItem {\n name: string;\n commit: {\n sha: string;\n url: string;\n };\n protected: boolean;\n}\n\n/**\n * Options for GitHubClient\n */\nexport interface GitHubClientOptions {\n auth?: AuthOptions;\n baseUrl?: string;\n cache?: CacheOptions;\n rateLimit?: RateLimitOptions;\n}\n\n/**\n * GitHub API client with throttling, retry, and caching\n */\nexport class GitHubClient {\n private octokit: Octokit;\n private cache: Map<string, CacheEntry> = new Map();\n private cacheConfig: CacheOptions;\n\n constructor(options: GitHubClientOptions) {\n this.cacheConfig = {\n enabled: options.cache?.enabled ?? true,\n ttl: options.cache?.ttl ?? 60000,\n };\n\n const maxRetries = options.rateLimit?.maxRetries ?? 3;\n\n // Create Octokit with plugins\n const OctokitWithPlugins = Octokit.plugin(throttling, retry);\n\n this.octokit = new OctokitWithPlugins({\n auth: options.auth?.token,\n baseUrl: options.baseUrl ?? \"https://api.github.com\",\n // Suppress Octokit's built-in request logging (from @octokit/plugin-request-log)\n // We handle errors ourselves with user-friendly messages\n log: {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n },\n throttle: {\n onRateLimit: (retryAfter, _options, _octokit, retryCount) => {\n if (retryCount < maxRetries) {\n console.warn(`Rate limited. Retrying after ${retryAfter} seconds.`);\n return true;\n }\n return false;\n },\n onSecondaryRateLimit: (retryAfter, _options, _octokit, retryCount) => {\n if (retryCount < maxRetries) {\n console.warn(`Secondary rate limit. Retrying after ${retryAfter} seconds.`);\n return true;\n }\n return false;\n },\n },\n retry: {\n enabled: options.rateLimit?.autoRetry ?? true,\n retries: maxRetries,\n },\n });\n }\n\n /**\n * Make a request to the GitHub API\n */\n async request<T = unknown>(\n route: string,\n params?: Record<string, unknown>,\n ): Promise<{ data: T; status: number; headers: Record<string, string> }> {\n // Only cache GET requests\n const isGet = route.startsWith(\"GET \");\n\n if (isGet && this.cacheConfig.enabled) {\n const cacheKey = this.getCacheKey(route, params);\n const cached = this.getFromCache(cacheKey);\n if (cached !== undefined) {\n return cached as { data: T; status: number; headers: Record<string, string> };\n }\n }\n\n const response = await this.octokit.request(route, params);\n\n const result = {\n data: response.data as T,\n status: response.status,\n headers: response.headers as Record<string, string>,\n };\n\n // Cache GET responses\n if (isGet && this.cacheConfig.enabled) {\n const cacheKey = this.getCacheKey(route, params);\n this.setCache(cacheKey, result);\n }\n\n return result;\n }\n\n /**\n * Generate cache key from route and params\n */\n private getCacheKey(route: string, params?: Record<string, unknown>): string {\n return `${route}:${JSON.stringify(params ?? {})}`;\n }\n\n /**\n * Get from cache if not expired\n */\n private getFromCache(key: string): unknown | undefined {\n const entry = this.cache.get(key);\n if (!entry) return undefined;\n\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return undefined;\n }\n\n return entry.data;\n }\n\n /**\n * Set cache entry\n */\n private setCache(key: string, data: unknown): void {\n this.cache.set(key, {\n data,\n expiresAt: Date.now() + this.cacheConfig.ttl,\n });\n }\n\n /**\n * Clear the cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Get the underlying Octokit instance (for advanced usage)\n */\n getOctokit(): Octokit {\n return this.octokit;\n }\n\n // ============ Contents API Methods ============\n\n /**\n * Get repository contents at a path\n * @param owner Repository owner\n * @param repo Repository name\n * @param path Path within the repository (empty string for root)\n * @param ref Optional branch, tag, or commit SHA\n * @returns Contents item(s) - array for directories, single item for files\n */\n async getContents(\n owner: string,\n repo: string,\n path: string,\n ref?: string,\n ): Promise<ContentsResponse> {\n const params: Record<string, unknown> = {\n owner,\n repo,\n path: path || \"\",\n };\n\n if (ref) {\n params.ref = ref;\n }\n\n const response = await this.request<ContentsResponse>(\n \"GET /repos/{owner}/{repo}/contents/{path}\",\n params,\n );\n\n return response.data;\n }\n\n /**\n * Get blob content for large files (>1MB)\n * @param owner Repository owner\n * @param repo Repository name\n * @param sha Blob SHA\n * @returns Decoded content as string\n */\n async getBlob(owner: string, repo: string, sha: string): Promise<string> {\n const response = await this.request<{ content: string; encoding: string }>(\n \"GET /repos/{owner}/{repo}/git/blobs/{sha}\",\n { owner, repo, sha },\n );\n\n // Blob API always returns base64 encoded content\n return Buffer.from(response.data.content, \"base64\").toString(\"utf-8\");\n }\n\n /**\n * Get repository branches\n * @param owner Repository owner\n * @param repo Repository name\n * @returns Array of branch items\n */\n async getBranches(owner: string, repo: string): Promise<BranchItem[]> {\n const allBranches: BranchItem[] = [];\n let page = 1;\n const perPage = 100;\n\n while (true) {\n const response = await this.request<BranchItem[]>(\"GET /repos/{owner}/{repo}/branches\", {\n owner,\n repo,\n per_page: perPage,\n page,\n });\n\n allBranches.push(...response.data);\n\n if (response.data.length < perPage) {\n break;\n }\n page++;\n }\n\n return allBranches;\n }\n\n /**\n * Get default branch for a repository\n * @param owner Repository owner\n * @param repo Repository name\n * @returns Default branch name\n */\n async getDefaultBranch(owner: string, repo: string): Promise<string> {\n const response = await this.request<{ default_branch: string }>(\"GET /repos/{owner}/{repo}\", {\n owner,\n repo,\n });\n\n return response.data.default_branch;\n }\n}\n","/**\n * Type definitions for AFSGitHub provider\n */\n\nimport { z } from \"zod\";\n\n/**\n * Authentication options\n */\nexport const authOptionsSchema = z.object({\n /** Personal Access Token */\n token: z.string().optional(),\n});\n\nexport type AuthOptions = z.infer<typeof authOptionsSchema>;\n\n/**\n * Cache configuration\n */\nexport const cacheOptionsSchema = z.object({\n /** Enable caching */\n enabled: z.boolean().default(true),\n /** Cache TTL in milliseconds */\n ttl: z.number().default(60000),\n});\n\nexport type CacheOptions = z.infer<typeof cacheOptionsSchema>;\n\n/**\n * Rate limiting configuration\n */\nexport const rateLimitOptionsSchema = z.object({\n /** Enable automatic retry on rate limit */\n autoRetry: z.boolean().default(true),\n /** Maximum retry attempts */\n maxRetries: z.number().default(3),\n});\n\nexport type RateLimitOptions = z.infer<typeof rateLimitOptionsSchema>;\n\n/**\n * Access mode for the provider\n */\nexport const accessModeSchema = z.enum([\"readonly\", \"readwrite\"]).default(\"readonly\");\n\nexport type AccessMode = z.infer<typeof accessModeSchema>;\n\n/**\n * Repository mode\n * - single-repo: Access a single repository (requires owner and repo)\n * - multi-repo: Access multiple repositories with full paths\n * - org: Access all repositories in an organization (requires owner only)\n */\nexport const repoModeSchema = z.enum([\"single-repo\", \"multi-repo\", \"org\"]).default(\"single-repo\");\n\nexport type RepoMode = z.infer<typeof repoModeSchema>;\n\n/**\n * Owner type for org mode\n * - org: GitHub organization (uses /orgs/{org}/repos endpoint)\n * - user: GitHub user account (uses /users/{username}/repos endpoint)\n * - undefined: Auto-detect (tries org first, falls back to user)\n */\nexport const ownerTypeSchema = z.enum([\"org\", \"user\"]).optional();\n\nexport type OwnerType = z.infer<typeof ownerTypeSchema>;\n\n/**\n * Full options schema for AFSGitHub\n */\nexport const afsGitHubOptionsSchema = z.object({\n /** Module name */\n name: z.string().default(\"github\"),\n\n /** Module description */\n description: z.string().optional(),\n\n /** Authentication */\n auth: authOptionsSchema.optional(),\n\n /** Repository owner (required for single-repo mode) */\n owner: z.string().optional(),\n\n /** Repository name (required for single-repo mode) */\n repo: z.string().optional(),\n\n /** Access mode */\n accessMode: accessModeSchema.optional(),\n\n /** Repository mode */\n mode: repoModeSchema.optional(),\n\n /** Owner type (org or user). If not set, auto-detects by trying org first. */\n ownerType: ownerTypeSchema.optional(),\n\n /** GitHub API base URL (for Enterprise) */\n baseUrl: z.string().default(\"https://api.github.com\"),\n\n /** Custom mapping path (overrides default) */\n mappingPath: z.string().optional(),\n\n /** Cache configuration */\n cache: cacheOptionsSchema.optional(),\n\n /** Rate limiting configuration */\n rateLimit: rateLimitOptionsSchema.optional(),\n\n /** Default branch/ref for Contents API (optional) */\n ref: z.string().optional(),\n});\n\n/**\n * Input options type (what users provide, with optional fields)\n */\nexport type AFSGitHubOptions = z.input<typeof afsGitHubOptionsSchema>;\n\n/**\n * Output options type (after Zod parsing, with defaults applied)\n */\nexport type AFSGitHubOptionsParsed = z.infer<typeof afsGitHubOptionsSchema>;\n\n/**\n * Validated options with defaults applied\n */\nexport interface AFSGitHubOptionsResolved {\n name: string;\n description?: string;\n auth?: AuthOptions;\n owner?: string;\n repo?: string;\n accessMode: AccessMode;\n mode: RepoMode;\n ownerType?: OwnerType;\n baseUrl: string;\n mappingPath?: string;\n cache: CacheOptions;\n rateLimit: RateLimitOptions;\n ref?: string;\n}\n","/**\n * AFSGitHub Provider\n *\n * AFS module for accessing GitHub Issues, PRs, and Actions.\n * Implements AFSModule and AFSWorldMappingCapable interfaces.\n */\n\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n AFSEntry,\n AFSListOptions,\n AFSListResult,\n AFSModule,\n AFSReadOptions,\n AFSReadResult,\n AFSRoot,\n AFSWorldMappingCapable,\n ExternalRef,\n MappingStatus,\n MutateAction,\n MutateResult,\n ProjectionContext,\n} from \"@aigne/afs\";\nimport { type CompiledMapping, MappingCompiler, type RouteDefinition } from \"@aigne/afs-mapping\";\nimport { type WorldBinding, WorldMappingCore } from \"@aigne/afs-world-mapping\";\nimport { GitHubClient } from \"./client.js\";\nimport {\n type AFSGitHubOptions,\n type AFSGitHubOptionsResolved,\n afsGitHubOptionsSchema,\n} from \"./types.js\";\n\n// Get the directory of this module for default mapping\nconst __dirname = fileURLToPath(new URL(\".\", import.meta.url));\nconst DEFAULT_MAPPING_PATH = join(__dirname, \"default-mapping\");\n\n/**\n * AFSGitHub Provider\n *\n * Provides access to GitHub Issues, Pull Requests, and Actions through AFS.\n *\n * @example\n * ```typescript\n * const github = new AFSGitHub({\n * auth: { token: process.env.GITHUB_TOKEN },\n * owner: \"aigne\",\n * repo: \"afs\",\n * });\n *\n * // Mount to AFS\n * afs.mount(\"/github\", github);\n *\n * // List issues\n * const issues = await afs.list(\"/github/issues\");\n * ```\n */\nexport class AFSGitHub implements AFSModule, AFSWorldMappingCapable {\n readonly name: string;\n readonly description?: string;\n readonly accessMode: \"readonly\" | \"readwrite\";\n\n private options: AFSGitHubOptionsResolved;\n private client: GitHubClient;\n private compiled: CompiledMapping | null = null;\n private mappingPath: string | null = null;\n private mappingLoadedAt?: Date;\n private mappingError?: string;\n\n /** World mapping core for schema-level path resolution and field projection (Level 1) */\n readonly worldCore: WorldMappingCore;\n\n constructor(options: AFSGitHubOptions) {\n // Validate and apply defaults\n const parsed = afsGitHubOptionsSchema.parse(options);\n\n this.options = {\n name: parsed.name,\n description: parsed.description,\n auth: parsed.auth,\n owner: parsed.owner,\n repo: parsed.repo,\n accessMode: parsed.accessMode ?? \"readonly\",\n mode: parsed.mode ?? \"single-repo\",\n ownerType: parsed.ownerType,\n baseUrl: parsed.baseUrl,\n mappingPath: parsed.mappingPath,\n cache: {\n enabled: parsed.cache?.enabled ?? true,\n ttl: parsed.cache?.ttl ?? 60000,\n },\n rateLimit: {\n autoRetry: parsed.rateLimit?.autoRetry ?? true,\n maxRetries: parsed.rateLimit?.maxRetries ?? 3,\n },\n ref: parsed.ref,\n };\n\n this.name = this.options.name;\n this.description = this.options.description;\n this.accessMode = this.options.accessMode;\n\n // Validate mode requirements\n if (this.options.mode === \"single-repo\") {\n if (!this.options.owner || !this.options.repo) {\n throw new Error(\"owner and repo are required in single-repo mode\");\n }\n } else if (this.options.mode === \"org\") {\n if (!this.options.owner) {\n throw new Error(\"owner is required in org mode\");\n }\n // Trim whitespace from owner\n this.options.owner = this.options.owner.trim();\n }\n\n // Create GitHub client\n this.client = new GitHubClient({\n auth: this.options.auth,\n baseUrl: this.options.baseUrl,\n cache: this.options.cache,\n rateLimit: this.options.rateLimit,\n });\n\n // Initialize world mapping core (Level 1: Library usage)\n this.worldCore = new WorldMappingCore(\n this.getDefaultWorldSchema(),\n this.getDefaultWorldBinding(),\n );\n\n // Load default mapping synchronously\n this.loadDefaultMapping();\n }\n\n /**\n * Load the default mapping configuration\n */\n private loadDefaultMapping(): void {\n try {\n const compiler = new MappingCompiler();\n // Use synchronous file reading for constructor\n // In practice, we compile from the directory\n const mappingPath = this.options.mappingPath ?? DEFAULT_MAPPING_PATH;\n this.mappingPath = mappingPath;\n\n // Load synchronously by reading files directly\n // This is a simplified version - in production, we'd use async\n this.compiled = compiler.compileConfig({\n name: \"github\",\n version: \"1.0\",\n defaults: {\n baseUrl: this.options.baseUrl,\n headers: {\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n },\n },\n routes: this.getDefaultRoutes(),\n });\n\n this.mappingLoadedAt = new Date();\n this.mappingError = undefined;\n } catch (error) {\n this.mappingError = error instanceof Error ? error.message : String(error);\n }\n }\n\n /**\n * Get default route definitions\n * This is used when loading mapping synchronously\n */\n private getDefaultRoutes(): Record<string, RouteDefinition> {\n return {\n \"/{owner}/{repo}/issues\": {\n list: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/issues\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n state: 'query.state | default(\"open\")',\n per_page: \"query.limit | default(30)\",\n },\n transform: {\n items: \"$\",\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/issues/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n metadata: {\n type: \"issue\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n \"/{owner}/{repo}/issues/{number}\": {\n read: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/issues/{number}\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n number: \"path.number\",\n },\n transform: {\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/issues/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n metadata: {\n type: \"issue\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n \"/{owner}/{repo}/pulls\": {\n list: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/pulls\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n state: 'query.state | default(\"open\")',\n per_page: \"query.limit | default(30)\",\n },\n transform: {\n items: \"$\",\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/pulls/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n metadata: {\n type: \"pull_request\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n \"/{owner}/{repo}/pulls/{number}\": {\n read: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/pulls/{number}\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n number: \"path.number\",\n },\n transform: {\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/pulls/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n metadata: {\n type: \"pull_request\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n };\n }\n\n /**\n * Get default world schema for GitHub\n * Defines Issue, PullRequest, Comment as world kinds\n */\n private getDefaultWorldSchema(): any {\n return {\n world: \"github\",\n version: \"1.0\",\n kinds: {\n Issue: {\n key: \"number\",\n path: \"/{owner}/{repo}/issues/{number}\",\n fields: {\n number: \"int\",\n title: \"string\",\n body: \"text\",\n state: \"string\",\n author: \"string\",\n labels: \"string\",\n assignees: \"string\",\n created_at: \"datetime\",\n updated_at: \"datetime\",\n comments_count: \"int\",\n },\n },\n PullRequest: {\n key: \"number\",\n path: \"/{owner}/{repo}/pulls/{number}\",\n fields: {\n number: \"int\",\n title: \"string\",\n body: \"text\",\n state: \"string\",\n author: \"string\",\n created_at: \"datetime\",\n updated_at: \"datetime\",\n },\n },\n Comment: {\n key: \"id\",\n path: \"/{owner}/{repo}/issues/{number}/comments/{id}\",\n fields: {\n id: \"int\",\n body: \"text\",\n author: \"string\",\n created_at: \"datetime\",\n updated_at: \"datetime\",\n },\n },\n },\n };\n }\n\n /**\n * Get default world binding for GitHub\n * Maps world fields to GitHub API response fields\n */\n private getDefaultWorldBinding(): WorldBinding {\n return {\n source: \"/github\",\n mappings: {\n Issue: {\n path: \"/{owner}/{repo}/issues/{number}\",\n fieldMap: {\n author: \"user_login\",\n comments_count: \"comments\",\n },\n },\n PullRequest: {\n path: \"/{owner}/{repo}/pulls/{number}\",\n fieldMap: {\n author: \"user_login\",\n },\n },\n Comment: {\n path: \"/{owner}/{repo}/issues/{number}/comments/{id}\",\n fieldMap: {\n author: \"user_login\",\n },\n },\n },\n };\n }\n\n // ============ AFSModule Methods ============\n\n onMount?(_root: AFSRoot): void {\n // Optional: Initialize resources when mounted\n }\n\n /**\n * Resolve a path based on mode\n * - single-repo: prepend owner/repo\n * - org: prepend owner (org name)\n * - multi-repo: pass through\n */\n resolvePath(path: string): string {\n // First, try to decode URL-encoded characters\n let decodedPath: string;\n try {\n decodedPath = decodeURIComponent(path);\n } catch {\n decodedPath = path;\n }\n\n // Normalize: split by slashes, filter empty and traversal segments, rejoin\n const segments = decodedPath\n .split(\"/\")\n .filter((segment) => segment !== \"\" && segment !== \".\" && segment !== \"..\");\n\n const cleanPath = segments.join(\"/\");\n\n if (this.options.mode === \"single-repo\" && this.options.owner && this.options.repo) {\n // Prepend owner/repo to path\n if (!cleanPath) {\n return `/${this.options.owner}/${this.options.repo}`;\n }\n return `/${this.options.owner}/${this.options.repo}/${cleanPath}`;\n }\n\n if (this.options.mode === \"org\" && this.options.owner) {\n // For org mode:\n // - \"/\" or \"\" -> \"/\" (org root, will list repos)\n // - \"/repo\" -> \"/owner/repo\" (repo root)\n // - \"/repo/issues\" -> \"/owner/repo/issues\"\n if (!cleanPath) {\n return \"/\";\n }\n return `/${this.options.owner}/${cleanPath}`;\n }\n\n // multi-repo mode: pass through (with normalization)\n return cleanPath ? `/${cleanPath}` : \"/\";\n }\n\n /**\n * Get virtual directory structure for root path\n * Returns the available resource types (issues, pulls, repo)\n */\n private getVirtualDirectories(): AFSEntry[] {\n return [\n {\n id: \"issues\",\n path: \"/issues\",\n summary: \"Repository Issues\",\n metadata: {\n childrenCount: -1, // Unknown count, but indicates it's a directory\n description: \"List and read repository issues\",\n },\n },\n {\n id: \"pulls\",\n path: \"/pulls\",\n summary: \"Pull Requests\",\n metadata: {\n childrenCount: -1, // Unknown count, but indicates it's a directory\n description: \"List and read pull requests\",\n },\n },\n {\n id: \"repo\",\n path: \"/repo\",\n summary: \"Repository Code\",\n metadata: {\n childrenCount: -1, // Unknown until accessed\n description: \"Repository source code (via Contents API)\",\n },\n },\n ];\n }\n\n /**\n * Check if path is root or empty\n */\n private isRootPath(path: string): boolean {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n return normalized === \"\";\n }\n\n /**\n * Get root entry (the mount point itself)\n */\n private getRootEntry(): AFSEntry {\n let summary: string;\n let childrenCount: number;\n\n if (this.options.mode === \"org\") {\n summary = this.description ?? `GitHub Organization: ${this.options.owner}`;\n childrenCount = -1; // Unknown until repos are fetched\n } else if (this.options.mode === \"single-repo\") {\n summary = this.description ?? `GitHub: ${this.options.owner}/${this.options.repo}`;\n childrenCount = 3; // issues, pulls, repo\n } else {\n summary = this.description ?? \"GitHub\";\n childrenCount = -1;\n }\n\n return {\n id: this.name,\n path: \"/\",\n summary,\n metadata: {\n childrenCount,\n description: summary,\n },\n };\n }\n\n /**\n * Get virtual directories for a repo (issues, pulls, repo)\n */\n private getRepoVirtualDirectories(repoPath: string): AFSEntry[] {\n return [\n {\n id: `${repoPath}/issues`,\n path: `${repoPath}/issues`,\n summary: \"Repository Issues\",\n metadata: {\n childrenCount: -1,\n description: \"List and read repository issues\",\n },\n },\n {\n id: `${repoPath}/pulls`,\n path: `${repoPath}/pulls`,\n summary: \"Pull Requests\",\n metadata: {\n childrenCount: -1,\n description: \"List and read pull requests\",\n },\n },\n {\n id: `${repoPath}/repo`,\n path: `${repoPath}/repo`,\n summary: \"Repository Code\",\n metadata: {\n childrenCount: -1,\n description: \"Repository source code (via Contents API)\",\n },\n },\n ];\n }\n\n /**\n * Check if a path represents a repo root in org mode\n * e.g., \"/reponame\" without /issues or /pulls suffix\n */\n private isRepoRootPath(path: string): boolean {\n const segments = path\n .replace(/^\\/+|\\/+$/g, \"\")\n .split(\"/\")\n .filter(Boolean);\n return segments.length === 1;\n }\n\n /**\n * Format a user-friendly error message based on the error type\n */\n private formatErrorMessage(error: unknown, context: string): string {\n const status = (error as { status?: number })?.status;\n const message = error instanceof Error ? error.message : String(error);\n\n // Sanitize any tokens from the message\n const sanitized = message.replace(/ghp_[a-zA-Z0-9]+/g, \"[REDACTED]\");\n\n if (status === 401 || message.includes(\"Bad credentials\")) {\n if (!this.options.auth?.token) {\n return `GitHub authentication required for ${context}. Set GITHUB_TOKEN environment variable or provide auth.token in config.`;\n }\n return `GitHub token is invalid or expired. Please check your GITHUB_TOKEN and ensure it has the required permissions.`;\n }\n\n if (status === 403) {\n if (message.includes(\"rate limit\")) {\n return `GitHub API rate limit exceeded. ${this.options.auth?.token ? \"Your token may have hit its limit.\" : \"Set GITHUB_TOKEN for higher rate limits (5000/hour vs 60/hour).\"} Try again later.`;\n }\n return `GitHub access forbidden for ${context}. Check that your token has the required permissions (repo scope for private repos).`;\n }\n\n if (status === 404) {\n return `GitHub ${context} not found. Check that the organization/user name is correct and accessible.`;\n }\n\n if (message.includes(\"ENOTFOUND\") || message.toLowerCase().includes(\"network\")) {\n return `Network error connecting to GitHub. Check your internet connection.`;\n }\n\n return `GitHub API error: ${sanitized}`;\n }\n\n // ============ Contents API Methods ============\n\n /**\n * Check if a path is a repo path (should be routed to Contents API)\n * - Single-repo mode: /repo or /repo/*\n * - Org mode: /{repoName}/repo or /{repoName}/repo/*\n */\n private isRepoPath(path: string): boolean {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /repo or /repo/*\n return segments[0] === \"repo\";\n }\n\n if (this.options.mode === \"org\") {\n // /{repoName}/repo or /{repoName}/repo/*\n return segments.length >= 2 && segments[1] === \"repo\";\n }\n\n return false;\n }\n\n /**\n * Parse a repo path into owner, repo name, branch, and file path\n * Structure: /repo/{branch}/{filePath}\n * - Single-repo mode: /repo/main/src/index.ts -> { owner, repo, branch: \"main\", filePath: \"src/index.ts\" }\n * - Org mode: /afs/repo/main/src/index.ts -> { owner, repo: \"afs\", branch: \"main\", filePath: \"src/index.ts\" }\n */\n private parseRepoPath(path: string): {\n owner: string;\n repo: string;\n branch?: string;\n filePath: string;\n } {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /repo -> list branches\n // /repo/{branch} -> list branch root\n // /repo/{branch}/... -> access files\n const branch = segments[1]; // undefined if just /repo\n const filePath = segments.slice(2).join(\"/\");\n return {\n owner: this.options.owner!,\n repo: this.options.repo!,\n branch,\n filePath,\n };\n }\n\n if (this.options.mode === \"org\") {\n // /{repoName}/repo -> list branches\n // /{repoName}/repo/{branch} -> list branch root\n // /{repoName}/repo/{branch}/... -> access files\n const repoName = segments[0]!;\n const branch = segments[2]; // undefined if just /{repoName}/repo\n const filePath = segments.slice(3).join(\"/\");\n return {\n owner: this.options.owner!,\n repo: repoName,\n branch,\n filePath,\n };\n }\n\n // multi-repo mode - shouldn't normally reach here\n return {\n owner: this.options.owner!,\n repo: this.options.repo!,\n branch: undefined,\n filePath: \"\",\n };\n }\n\n /**\n * Build the path prefix for a repo entry\n */\n private getRepoPathPrefix(repo: string): string {\n return this.options.mode === \"single-repo\" ? \"/repo\" : `/${repo}/repo`;\n }\n\n /**\n * List repository contents via GitHub Contents API\n * - /repo -> list all branches\n * - /repo/{branch} -> list branch root\n * - /repo/{branch}/path -> list contents at path\n */\n private async listViaContentsAPI(\n path: string,\n _options?: AFSListOptions,\n ): Promise<AFSListResult> {\n const { owner, repo, branch, filePath } = this.parseRepoPath(path);\n const repoPrefix = this.getRepoPathPrefix(repo);\n\n // Case 1: No branch specified - list all branches\n if (!branch) {\n try {\n const branches = await this.client.getBranches(owner, repo);\n const defaultBranch = await this.client.getDefaultBranch(owner, repo);\n\n const entries: AFSEntry[] = branches.map((b) => ({\n id: `${repoPrefix}/${b.name}`,\n path: `${repoPrefix}/${b.name}`,\n summary: b.name + (b.name === defaultBranch ? \" (default)\" : \"\"),\n metadata: {\n type: \"branch\",\n sha: b.commit.sha,\n protected: b.protected,\n isDefault: b.name === defaultBranch,\n childrenCount: -1, // Unknown until accessed\n },\n }));\n\n return { data: entries };\n } catch (error) {\n return {\n data: [],\n message: this.formatErrorMessage(error, `branches for ${owner}/${repo}`),\n };\n }\n }\n\n // Case 2 & 3: Branch specified - list contents (root or path)\n try {\n const contents = await this.client.getContents(owner, repo, filePath, branch);\n\n // Handle single file response (shouldn't happen for list, but be defensive)\n if (!Array.isArray(contents)) {\n const entryPath = filePath\n ? `${repoPrefix}/${branch}/${contents.path}`\n : `${repoPrefix}/${branch}/${contents.name}`;\n return {\n data: [\n {\n id: entryPath,\n path: entryPath,\n summary: contents.name,\n metadata: {\n type: contents.type,\n size: contents.size,\n sha: contents.sha,\n childrenCount: contents.type === \"dir\" ? -1 : undefined,\n },\n },\n ],\n };\n }\n\n const entries: AFSEntry[] = contents.map((item) => {\n const entryPath = filePath\n ? `${repoPrefix}/${branch}/${filePath}/${item.name}`\n : `${repoPrefix}/${branch}/${item.name}`;\n return {\n id: entryPath,\n path: entryPath,\n summary: item.name,\n metadata: {\n type: item.type,\n size: item.size,\n sha: item.sha,\n childrenCount: item.type === \"dir\" ? -1 : undefined,\n },\n };\n });\n\n return { data: entries };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n return { data: [], message: `Path not found: ${branch}/${filePath || \"\"}` };\n }\n return {\n data: [],\n message: this.formatErrorMessage(error, `repository contents for ${owner}/${repo}`),\n };\n }\n }\n\n /**\n * Read file content via GitHub Contents API\n * Path format: /repo/{branch}/{filePath}\n */\n private async readViaContentsAPI(\n path: string,\n _options?: AFSReadOptions,\n ): Promise<AFSReadResult> {\n const { owner, repo, branch, filePath } = this.parseRepoPath(path);\n const repoPrefix = this.getRepoPathPrefix(repo);\n\n if (!branch) {\n // Can't read /repo without a branch\n return { data: undefined, message: \"Branch is required to read files\" };\n }\n\n if (!filePath) {\n // Can't read branch root as a file\n return { data: undefined, message: \"Cannot read branch root as file\" };\n }\n\n try {\n const contents = await this.client.getContents(owner, repo, filePath, branch);\n\n // Handle directory response\n if (Array.isArray(contents)) {\n return { data: undefined, message: \"Path is a directory, not a file\" };\n }\n\n if (contents.type !== \"file\") {\n return { data: undefined, message: `Path is a ${contents.type}, not a file` };\n }\n\n // Get file content\n let content: string;\n if (contents.content) {\n // Decode base64 content (for files <1MB)\n content = Buffer.from(contents.content, \"base64\").toString(\"utf-8\");\n } else {\n // Large file - fetch via Blob API\n content = await this.client.getBlob(owner, repo, contents.sha);\n }\n\n const entryPath = `${repoPrefix}/${branch}/${filePath}`;\n return {\n data: {\n id: entryPath,\n path: entryPath,\n summary: contents.name,\n content,\n metadata: {\n type: \"file\",\n size: contents.size,\n sha: contents.sha,\n branch,\n },\n },\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n return { data: undefined, message: `File not found: ${branch}/${filePath}` };\n }\n return {\n data: undefined,\n message: this.formatErrorMessage(error, `file ${filePath} in ${owner}/${repo}@${branch}`),\n };\n }\n }\n\n /**\n * List organization or user repositories\n * Uses ownerType if specified, otherwise tries org endpoint first and falls back to user\n */\n private async listOrgRepos(includePrivate: boolean): Promise<AFSListResult> {\n const owner = this.options.owner!;\n const ownerType = this.options.ownerType;\n let allRepos: Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }> = [];\n\n // If ownerType is explicitly set, use it directly without fallback\n if (ownerType) {\n try {\n allRepos = await this.fetchAllRepos(ownerType, owner, includePrivate);\n } catch (error) {\n const context = ownerType === \"org\" ? `organization \"${owner}\"` : `user \"${owner}\"`;\n return { data: [], message: this.formatErrorMessage(error, context) };\n }\n } else {\n // Auto-detect: try org first, fall back to user\n try {\n allRepos = await this.fetchAllRepos(\"org\", owner, includePrivate);\n } catch (error) {\n // If 404, try user endpoint (could be a user account, not an org)\n const is404 =\n (error instanceof Error && error.message.includes(\"404\")) ||\n (error as { status?: number })?.status === 404;\n if (is404) {\n try {\n allRepos = await this.fetchAllRepos(\"user\", owner, includePrivate);\n } catch (userError) {\n // Both org and user endpoints failed\n const status = (userError as { status?: number })?.status;\n if (status === 404) {\n return {\n data: [],\n message: `GitHub organization or user \"${owner}\" not found. Check that the name is correct.`,\n };\n }\n return { data: [], message: this.formatErrorMessage(userError, `user \"${owner}\"`) };\n }\n } else {\n return { data: [], message: this.formatErrorMessage(error, `organization \"${owner}\"`) };\n }\n }\n }\n\n // Filter out private repos if no auth token\n const filteredRepos = this.options.auth?.token ? allRepos : allRepos.filter((r) => !r.private);\n\n const entries: AFSEntry[] = filteredRepos.map((repo) => ({\n id: repo.name,\n path: `/${repo.name}`,\n summary: repo.description || repo.name,\n metadata: {\n childrenCount: 3, // issues, pulls, repo\n description: repo.description,\n private: repo.private,\n },\n }));\n\n return { data: entries };\n }\n\n /**\n * Fetch all repos with pagination support\n */\n private async fetchAllRepos(\n type: \"org\" | \"user\",\n owner: string,\n includePrivate: boolean,\n ): Promise<\n Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }>\n > {\n const allRepos: Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }> = [];\n\n let page = 1;\n const perPage = 100;\n\n while (true) {\n let response: { data: unknown; status: number; headers: Record<string, string> };\n if (type === \"org\") {\n response = await this.client.request(\"GET /orgs/{org}/repos\", {\n org: owner,\n per_page: perPage,\n page,\n type: includePrivate ? \"all\" : \"public\",\n });\n } else {\n response = await this.client.request(\"GET /users/{username}/repos\", {\n username: owner,\n per_page: perPage,\n page,\n type: includePrivate ? \"all\" : \"public\",\n });\n }\n\n const repos = response.data as Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }>;\n\n allRepos.push(...repos);\n\n // If we got fewer than perPage, we've reached the end\n if (repos.length < perPage) {\n break;\n }\n page++;\n }\n\n return allRepos;\n }\n\n /**\n * List entries at a path\n */\n async list(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n const maxDepth = options?.maxDepth ?? 1;\n\n // Route /repo paths to Contents API\n if (this.isRepoPath(path)) {\n return this.listViaContentsAPI(path, options);\n }\n\n // Handle root path\n if (this.isRootPath(path)) {\n // maxDepth 0 means return info about the path itself (the mount point)\n if (maxDepth === 0) {\n return { data: [this.getRootEntry()] };\n }\n\n // For org mode, list repositories\n if (this.options.mode === \"org\") {\n return this.listOrgRepos(!!this.options.auth?.token);\n }\n\n // For single-repo mode, return virtual directories (issues, pulls)\n return { data: this.getVirtualDirectories() };\n }\n\n // In org mode, check if this is a repo root (e.g., \"/afs\")\n if (this.options.mode === \"org\" && this.isRepoRootPath(path)) {\n const repoName = path.replace(/^\\/+|\\/+$/g, \"\");\n\n if (maxDepth === 0) {\n // Return info about the repo itself\n return {\n data: [\n {\n id: repoName,\n path: `/${repoName}`,\n summary: `Repository: ${this.options.owner}/${repoName}`,\n metadata: {\n childrenCount: 2, // issues and pulls\n },\n },\n ],\n };\n }\n\n // Return virtual directories for this repo\n return { data: this.getRepoVirtualDirectories(`/${repoName}`) };\n }\n\n const fullPath = this.resolvePath(path);\n\n if (!this.compiled) {\n return { data: [], message: \"Mapping not loaded\" };\n }\n\n const resolved = this.compiled.resolve(fullPath);\n if (!resolved || !resolved.operations.list) {\n return { data: [], message: `No list operation for path: ${fullPath}` };\n }\n\n const request = this.compiled.buildRequest(fullPath, \"list\", {\n query: options?.filter as Record<string, string> | undefined,\n });\n\n if (!request) {\n return { data: [], message: \"Failed to build request\" };\n }\n\n try {\n const response = await this.client.request(\n `${request.method} ${request.path}`,\n request.params as Record<string, unknown>,\n );\n\n // Filter out PRs from issues list\n // GitHub's issues API returns both issues and PRs, but PRs have a `pull_request` field\n let responseData = response.data;\n if (Array.isArray(responseData) && fullPath.endsWith(\"/issues\")) {\n responseData = responseData.filter(\n (item: { pull_request?: unknown }) => !item.pull_request,\n );\n }\n\n const entries = this.compiled.projectResponse(fullPath, \"list\", responseData);\n\n // Adjust paths based on mode\n if (this.options.mode === \"single-repo\") {\n const prefix = `/${this.options.owner}/${this.options.repo}`;\n for (const entry of entries) {\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n }\n } else if (this.options.mode === \"org\") {\n // In org mode, strip the owner prefix to show paths like /repo/issues/123\n const prefix = `/${this.options.owner}`;\n for (const entry of entries) {\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n }\n }\n\n return { data: entries };\n } catch (error) {\n return {\n data: [],\n message: this.formatErrorMessage(error, `path \"${path}\"`),\n };\n }\n }\n\n /**\n * Read a single entry\n */\n async read(path: string, options?: AFSReadOptions): Promise<AFSReadResult> {\n // Route /repo paths to Contents API\n if (this.isRepoPath(path)) {\n return this.readViaContentsAPI(path, options);\n }\n\n // Security: validate path segments for numeric IDs where expected\n if (this.options.mode === \"org\" || this.options.mode === \"single-repo\") {\n const segments = path.replace(/^\\/+|\\/+$/g, \"\").split(\"/\");\n // Check for issues/{number} or pulls/{number} pattern\n const issuesIdx = segments.indexOf(\"issues\");\n const pullsIdx = segments.indexOf(\"pulls\");\n\n if (issuesIdx !== -1 && segments[issuesIdx + 1]) {\n const issueNum = segments[issuesIdx + 1];\n if (!/^\\d+$/.test(issueNum!)) {\n return { data: undefined, message: \"Invalid issue number\" };\n }\n }\n if (pullsIdx !== -1 && segments[pullsIdx + 1]) {\n const prNum = segments[pullsIdx + 1];\n if (!/^\\d+$/.test(prNum!)) {\n return { data: undefined, message: \"Invalid pull request number\" };\n }\n }\n }\n\n const fullPath = this.resolvePath(path);\n\n if (!this.compiled) {\n return { data: undefined, message: \"Mapping not loaded\" };\n }\n\n const resolved = this.compiled.resolve(fullPath);\n if (!resolved || !resolved.operations.read) {\n return { data: undefined, message: `No read operation for path: ${fullPath}` };\n }\n\n const request = this.compiled.buildRequest(fullPath, \"read\", {});\n\n if (!request) {\n return { data: undefined, message: \"Failed to build request\" };\n }\n\n try {\n const response = await this.client.request(\n `${request.method} ${request.path}`,\n request.params as Record<string, unknown>,\n );\n\n const entries = this.compiled.projectResponse(fullPath, \"read\", response.data);\n\n if (entries.length === 0) {\n return { data: undefined, message: \"No data returned\" };\n }\n\n const entry = entries[0]!;\n\n // Adjust path based on mode\n if (this.options.mode === \"single-repo\") {\n const prefix = `/${this.options.owner}/${this.options.repo}`;\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n } else if (this.options.mode === \"org\") {\n const prefix = `/${this.options.owner}`;\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n }\n\n return { data: entry };\n } catch (error) {\n return {\n data: undefined,\n message: this.formatErrorMessage(error, `path \"${path}\"`),\n };\n }\n }\n\n // ============ AFSWorldMappingCapable Methods ============\n\n async loadMapping(mappingPath: string): Promise<void> {\n const compiler = new MappingCompiler();\n try {\n this.compiled = await compiler.compileDirectory(mappingPath);\n this.mappingPath = mappingPath;\n this.mappingLoadedAt = new Date();\n this.mappingError = undefined;\n } catch (error) {\n this.mappingError = error instanceof Error ? error.message : String(error);\n throw error;\n }\n }\n\n async reloadMapping(): Promise<void> {\n if (!this.mappingPath) {\n throw new Error(\"No mapping path configured\");\n }\n\n const previousCompiled = this.compiled;\n try {\n await this.loadMapping(this.mappingPath);\n } catch (error) {\n // Rollback\n this.compiled = previousCompiled;\n throw error;\n }\n }\n\n getMappingStatus(): MappingStatus {\n return {\n loaded: this.compiled !== null,\n loadedAt: this.mappingLoadedAt,\n mappingPath: this.mappingPath ?? undefined,\n compiled: this.compiled !== null,\n error: this.mappingError,\n stats: this.compiled\n ? {\n routes: this.compiled.routeCount,\n operations: this.compiled.operationCount,\n }\n : undefined,\n };\n }\n\n resolve(path: string): ExternalRef | null {\n const fullPath = this.resolvePath(path);\n\n if (!this.compiled) return null;\n\n const resolved = this.compiled.resolve(fullPath);\n if (!resolved) return null;\n\n // Determine operation type\n const operation = resolved.operations.read ?? resolved.operations.list;\n if (!operation) return null;\n\n const request = this.compiled.buildRequest(\n fullPath,\n resolved.operations.read ? \"read\" : \"list\",\n {},\n );\n\n if (!request) return null;\n\n return {\n type: \"http\",\n target: `${this.options.baseUrl}${request.path}`,\n method: request.method,\n params: { ...resolved.params, ...request.params },\n headers: request.headers,\n };\n }\n\n project(externalData: unknown, context: ProjectionContext): AFSEntry[] {\n if (!this.compiled) return [];\n\n const operationType = context.rule === \"list\" ? \"list\" : \"read\";\n return this.compiled.projectResponse(context.path, operationType, externalData);\n }\n\n async mutate(_path: string, _action: MutateAction, _payload: unknown): Promise<MutateResult> {\n // MVP: write operations not implemented yet\n return {\n success: false,\n error: \"Write operations not yet implemented\",\n };\n }\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@aigne/afs-github",
3
+ "version": "1.11.0-beta.6",
4
+ "description": "AFS GitHub Provider - Access GitHub Issues, PRs, and Actions as AFS paths",
5
+ "license": "UNLICENSED",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "author": "Arcblock <blocklet@arcblock.io> https://github.com/arcblock",
10
+ "homepage": "https://github.com/arcblock/afs",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/arcblock/afs"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/arcblock/afs/issues"
17
+ },
18
+ "type": "module",
19
+ "main": "./dist/index.cjs",
20
+ "module": "./dist/index.mjs",
21
+ "types": "./dist/index.d.cts",
22
+ "exports": {
23
+ ".": {
24
+ "require": "./dist/index.cjs",
25
+ "import": "./dist/index.mjs"
26
+ },
27
+ "./*": "./*"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "LICENSE",
32
+ "README.md",
33
+ "CHANGELOG.md"
34
+ ],
35
+ "dependencies": {
36
+ "@octokit/plugin-retry": "^7.2.1",
37
+ "@octokit/plugin-throttling": "^9.6.1",
38
+ "@octokit/rest": "^21.1.1",
39
+ "zod": "^3.25.67",
40
+ "@aigne/afs": "^1.11.0-beta.6",
41
+ "@aigne/afs-mapping": "^1.11.0-beta.6",
42
+ "@aigne/afs-world-mapping": "^1.11.0-beta.6"
43
+ },
44
+ "devDependencies": {
45
+ "@types/bun": "^1.3.6",
46
+ "npm-run-all": "^4.1.5",
47
+ "rimraf": "^6.1.2",
48
+ "tsdown": "0.20.0-beta.3",
49
+ "typescript": "5.9.2",
50
+ "@aigne/scripts": "0.0.0",
51
+ "@aigne/typescript-config": "0.0.0"
52
+ },
53
+ "scripts": {
54
+ "build": "tsdown",
55
+ "check-types": "tsc --noEmit",
56
+ "clean": "rimraf dist coverage",
57
+ "test": "bun test",
58
+ "test:coverage": "bun test --coverage --coverage-reporter=lcov --coverage-reporter=text"
59
+ }
60
+ }