# Octokit.js

The all-batteries-included GitHub SDK for Browsers, Node.js, and Deno. Octokit.js integrates three main Octokit libraries: API client for REST/GraphQL requests and authentication, App client for GitHub Apps with webhooks and OAuth support, and Action client for pre-authenticated single repository access.

## Package Information

- **Package Name**: octokit
- **Package Type**: npm
- **Language**: TypeScript
- **Installation**: `npm install octokit`

## Core Imports

```typescript
import { Octokit, App, OAuthApp, RequestError } from "octokit";
```

For CommonJS:

```javascript
const { Octokit, App, OAuthApp, RequestError } = require("octokit");
```

For pagination types:

```typescript
import type { PageInfoForward, PageInfoBackward } from "octokit";
```

## Basic Usage

```typescript
import { Octokit } from "octokit";

// Create an authenticated client
const octokit = new Octokit({
  auth: "your-token-here",
});

// Make REST API requests
const { data: user } = await octokit.rest.users.getAuthenticated();
console.log(`Hello, ${user.login}!`);

// Use GraphQL
const { repository } = await octokit.graphql(`
  query ($owner: String!, $name: String!) {
    repository(owner: $owner, name: $name) {
      stargazerCount
    }
  }
`, {
  owner: "octokit",
  name: "octokit.js"
});

// Paginate through REST API results
const issues = await octokit.paginate(octokit.rest.issues.listForRepo, {
  owner: "octokit",
  repo: "octokit.js"
});

// GraphQL pagination
const { allIssues } = await octokit.graphql.paginate(`
  query allIssues($owner: String!, $repo: String!, $cursor: String) {
    repository(owner: $owner, name: $repo) {
      issues(first: 100, after: $cursor) {
        nodes { title }
        pageInfo { hasNextPage, endCursor }
      }
    }
  }
`, { owner: "octokit", repo: "octokit.js" });
```

## Architecture

Octokit.js is built around a plugin architecture with these core components:

- **Core API Client**: Base GitHub API functionality with authentication and request handling
- **Plugin System**: Extensible architecture with built-in plugins for common use cases
- **REST Endpoint Methods**: Pre-configured methods for all GitHub REST API endpoints
- **GraphQL Support**: Query interface with pagination support for GitHub's GraphQL API
- **Retry & Throttling**: Automatic request retry and rate limiting handling
- **Multi-Platform**: Universal compatibility across browsers, Node.js, and Deno

## Capabilities

### Primary API Client

Core GitHub API client with REST, GraphQL, authentication, and built-in best practices including retry logic, rate limiting, and pagination.

```typescript { .api }
class Octokit {
  constructor(options?: OctokitOptions);
  
  // REST API methods (from plugin)
  rest: RestEndpointMethods;
  
  // Core request method
  request<T = any>(route: string, options?: RequestOptions): Promise<OctokitResponse<T>>;
  
  // GraphQL query method
  graphql<T = any>(query: string, variables?: Record<string, any>): Promise<T>;
  
  // GraphQL pagination method
  graphql: {
    paginate<T>(query: string, variables?: Record<string, any>): Promise<T>;
  };
  
  // Pagination for REST and GraphQL
  paginate<T>(
    method: Function,
    parameters?: Record<string, any>
  ): Promise<T[]>;
  
  // Pagination iterator for memory-efficient iteration
  paginate: {
    iterator<T>(
      method: Function,
      parameters?: Record<string, any>
    ): AsyncIterable<{ data: T[] }>;
  };
  
  // Authentication method
  auth(): Promise<Authentication>;
  
  // Logging interface
  log: {
    debug: (message: string, info?: object) => void;
    info: (message: string, info?: object) => void;
    warn: (message: string, info?: object) => void;
    error: (message: string, info?: object) => void;
  };
}

interface OctokitOptions {
  auth?: string | AuthInterface | AuthOptions;
  baseUrl?: string;
  request?: RequestOptions;
  userAgent?: string;
  throttle?: {
    onRateLimit?: (retryAfter: number, options: Required<EndpointDefaults>, octokit: Octokit) => boolean;
    onSecondaryRateLimit?: (retryAfter: number, options: Required<EndpointDefaults>, octokit: Octokit) => boolean;
  };
}

interface OctokitResponse<T> {
  status: number;
  url: string;
  headers: ResponseHeaders;
  data: T;
}

interface RequestOptions {
  method?: string;
  url?: string;
  headers?: Record<string, string>;
  body?: any;
  request?: {
    timeout?: number;
    retries?: number;
    retryDelay?: number;
  };
}

type RestEndpointMethods = {
  [scope: string]: {
    [method: string]: (parameters?: any) => Promise<OctokitResponse<any>>;
  };
};
```

**Usage Examples:**

```typescript
import { Octokit } from "octokit";

// Basic authentication
const octokit = new Octokit({
  auth: process.env.GITHUB_TOKEN,
});

// Custom configuration
const octokit = new Octokit({
  auth: "token",
  baseUrl: "https://api.github.com",
  userAgent: "my-app/1.0.0",
  throttle: {
    onRateLimit: (retryAfter, options, octokit) => {
      octokit.log.warn(`Request quota exhausted for request ${options.method} ${options.url}`);
      return true; // retry once
    },
  },
});

// Making requests
const repos = await octokit.rest.repos.listForAuthenticatedUser();

// Paginate all results
const issues = await octokit.paginate(octokit.rest.issues.listForRepo, {
  owner: "owner",
  repo: "repo"
});

// Memory-efficient pagination with iterator
for await (const { data: issues } of octokit.paginate.iterator(octokit.rest.issues.listForRepo, {
  owner: "owner",
  repo: "repo",
  per_page: 100
})) {
  for (const issue of issues) {
    console.log(`Issue #${issue.number}: ${issue.title}`);
  }
}
```

### GitHub App Client

Client for GitHub Apps with pre-configured Octokit integration, webhooks, and installation management.

```typescript { .api }
class App {
  constructor(options: AppOptions);
  
  // Pre-configured Octokit instance
  octokit: Octokit;
  
  // Get installation-specific Octokit client
  getInstallationOctokit(installationId: number): Promise<Octokit>;
  
  // Iterate through all repositories the app is installed on
  eachRepository: {
    iterator(): AsyncIterable<{ octokit: Octokit; repository: Repository }>;
  };
  
  // Webhook handling
  webhooks: {
    on: (event: string, handler: Function) => void;
    onAny: (handler: Function) => void;
    removeListener: (event: string, handler: Function) => void;
    verify: (payload: string, signature: string) => boolean;
    verifyAndReceive: (options: VerifyAndReceiveOptions) => Promise<void>;
  };
  
  // OAuth handling (if configured)
  oauth?: {
    on: (event: string, handler: Function) => void;
    createToken: (options: any) => Promise<any>;
  };
}

interface AppOptions {
  appId: number;
  privateKey: string;
  installationId?: number;
  clientId?: string;
  clientSecret?: string;
  webhooks?: {
    secret?: string;
  };
  oauth?: {
    clientId?: string;
    clientSecret?: string;
  };
  Octokit?: typeof Octokit;
}

interface Repository {
  id: number;
  name: string;
  full_name: string;
  owner: {
    login: string;
    id: number;
  };
  private: boolean;
  description?: string;
}

interface VerifyAndReceiveOptions {
  id: string;
  name: string;
  signature: string;
  payload: string;
}
```

**Usage Examples:**

```typescript
import { App } from "octokit";

// Create GitHub App
const app = new App({
  appId: 123456,
  privateKey: process.env.PRIVATE_KEY,
});

// Get installation client
const installationOctokit = await app.getInstallationOctokit(7654321);
const repos = await installationOctokit.rest.apps.listReposAccessibleToInstallation();

// Iterate through all repositories the app is installed on
for await (const { octokit, repository } of app.eachRepository.iterator()) {
  console.log(`Processing repository: ${repository.full_name}`);
  // Use octokit instance scoped to this repository
}

// Handle webhooks
app.webhooks.on("push", async ({ payload }) => {
  console.log(`Received push event for ${payload.repository.full_name}`);
});

// Verify and receive webhooks in serverless environments
await app.webhooks.verifyAndReceive({
  id: request.headers["x-github-delivery"],
  name: request.headers["x-github-event"],
  signature: request.headers["x-hub-signature-256"],
  payload: request.body,
});
```

### OAuth App Client

Client for OAuth Apps with pre-configured Octokit integration and OAuth flow handling.

```typescript { .api }
class OAuthApp {
  constructor(options: OAuthAppOptions);
  
  // Pre-configured Octokit instance
  octokit: Octokit;
  
  // Create user access token
  createToken(options: CreateTokenOptions): Promise<CreateTokenResult>;
  
  // Check token
  checkToken(options: CheckTokenOptions): Promise<CheckTokenResult>;
  
  // Reset token
  resetToken(options: ResetTokenOptions): Promise<ResetTokenResult>;
  
  // Delete token
  deleteToken(options: DeleteTokenOptions): Promise<void>;
  
  // Get user Octokit client
  getUserOctokit(options: GetUserOctokitOptions): Octokit;
}

interface OAuthAppOptions {
  clientId: string;
  clientSecret: string;
  Octokit?: typeof Octokit;
}

interface CreateTokenOptions {
  code: string;
  state?: string;
  redirectUrl?: string;
}

interface CreateTokenResult {
  token: string;
  scopes: string[];
  tokenType: string;
}

interface CheckTokenOptions {
  token: string;
}

interface CheckTokenResult {
  token: string;
  scopes: string[];
  app: AppInfo;
  user: UserInfo;
}

interface GetUserOctokitOptions {
  token: string;
}
```

**Usage Examples:**

```typescript
import { OAuthApp } from "octokit";

// Create OAuth App
const oauthApp = new OAuthApp({
  clientId: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
});

// Exchange code for token
const { token } = await oauthApp.createToken({
  code: "code-from-oauth-callback",
});

// Get user client
const userOctokit = oauthApp.getUserOctokit({ token });
const user = await userOctokit.rest.users.getAuthenticated();
```

### Request Error Handling

Specialized error class for GitHub API request failures with detailed error information.

```typescript { .api }
class RequestError extends Error {
  constructor(message: string, status: number, options: RequestErrorOptions);
  
  // HTTP status code
  status: number;
  
  // Request details
  request: {
    method: string;
    url: string;
    headers: Record<string, string>;
  };
  
  // Response details (if available)
  response?: {
    status: number;
    url: string;
    headers: Record<string, string>;
    data?: any;
  };
}

interface RequestErrorOptions {
  request: {
    method: string;
    url: string;
    headers: Record<string, string>;
  };
  response?: {
    status: number;
    url: string;
    headers: Record<string, string>;
    data?: any;
  };
}
```

**Usage Examples:**

```typescript
import { Octokit, RequestError } from "octokit";

const octokit = new Octokit({ auth: "invalid-token" });

try {
  await octokit.rest.users.getAuthenticated();
} catch (error) {
  if (error instanceof RequestError) {
    console.log(`GitHub API error: ${error.status} ${error.message}`);
    console.log(`Request: ${error.request.method} ${error.request.url}`);
    
    if (error.status === 401) {
      console.log("Authentication failed - check your token");
    } else if (error.status === 403) {
      console.log("Rate limit exceeded or insufficient permissions");
    }
  }
}
```

### Node.js Middleware

Express.js middleware for handling GitHub webhooks and OAuth flows in Node.js applications.

```typescript { .api }
function createNodeMiddleware(
  app: App,
  options?: NodeMiddlewareOptions
): (req: any, res: any, next?: Function) => void;

interface NodeMiddlewareOptions {
  pathPrefix?: string;
  onUnhandledRequest?: (req: any, res: any) => void;
}
```

**Usage Examples:**

```typescript
import express from "express";
import { App, createNodeMiddleware } from "octokit";

const app = new App({
  appId: 123456,
  privateKey: process.env.PRIVATE_KEY,
  webhooks: { secret: process.env.WEBHOOK_SECRET },
});

const expressApp = express();
expressApp.use(createNodeMiddleware(app));
expressApp.listen(3000);

// Webhooks will be handled at POST /api/github/webhooks
// OAuth callback at GET /api/github/oauth/callback
```

## Types

### Pagination Types

Types for GraphQL pagination handling.

```typescript { .api }
interface PageInfoForward {
  hasNextPage: boolean;
  endCursor?: string;
}

interface PageInfoBackward {
  hasPreviousPage: boolean;
  startCursor?: string;
}
```

### Authentication Types

```typescript { .api }
interface Authentication {
  type: "token" | "app" | "installation" | "oauth-app" | "oauth-user";
  token: string;
  tokenType?: "oauth" | "installation";
  installationId?: number;
  permissions?: Record<string, string>;
  repositoryIds?: number[];
  singleFileName?: string;
}

interface AuthInterface {
  (): Promise<Authentication>;
}

interface AuthOptions {
  appId?: number;
  privateKey?: string;
  installationId?: number;
  clientId?: string;
  clientSecret?: string;
  token?: string;
}
```

## Error Handling

Common error scenarios and handling patterns:

- **401 Unauthorized**: Invalid or expired authentication token
- **403 Forbidden**: Rate limit exceeded or insufficient permissions  
- **404 Not Found**: Repository, user, or resource doesn't exist
- **422 Unprocessable Entity**: Validation errors in request data

All API methods can throw `RequestError` instances that provide detailed error information including HTTP status codes, request details, and response data when available.