Skip to content

Repository files navigation

@lujax/github-sdk

npm versionCI

A TypeScript-first, ergonomic wrapper around the GitHub REST API. Calls api.github.com directly using native fetch — no Octokit, no third-party HTTP library.

  • Clean TypeScript domain types — camelCase interfaces instead of raw snake_case API responses
  • Typed errorsGithubApiError, InvalidTokenError, MissingConfigError instead of guessing at response shapes
  • Service-based APIgithub.pullRequests.list() instead of hand-building fetch calls
  • Built-in rate limiting, retries, and ETag caching — no extra config required
  • PAT or GitHub App auth, swappable behind one interface
  • Near-zero dependenciesjose for GitHub App JWT signing is the only runtime dependency

Installation

npm install @lujax/github-sdk

Requires Node.js 18 or later (uses native fetch).

Quick start

import{GithubClient}from"@lujax/github-sdk";constgithub=newGithubClient({token: process.env.GITHUB_TOKEN,owner: "lujax-dev",repo: "github-sdk",});constpullRequests=awaitgithub.pullRequests.list();constrepo=awaitgithub.repositories.get();

owner, repo, and org are all optional on GithubClientConfig — each service asserts the config it actually needs at construction time, throwing MissingConfigError immediately if something's missing rather than failing later on a request. A GithubClient instance is scoped to one owner/repo pair; to work with multiple repositories, create multiple clients.

Authentication

Personal Access Token (PAT)

The simplest option — pass a token string directly:

constgithub=newGithubClient({token: process.env.GITHUB_TOKEN,owner: "lujax-dev",repo: "github-sdk",});

GitHub App

For production use as a GitHub App, pass a GitHubAppAuth instance via auth instead of token. It signs a JWT from your App's private key, exchanges it for an installation access token, and refreshes it automatically as it nears expiry — no extra code required:

import{GithubClient,GitHubAppAuth}from"@lujax/github-sdk";constgithub=newGithubClient({auth: newGitHubAppAuth({appId: process.env.GITHUB_APP_ID,privateKey: process.env.GITHUB_APP_PRIVATE_KEY,installationId: process.env.GITHUB_APP_INSTALLATION_ID,}),owner: "lujax-dev",repo: "github-sdk",});

token and auth are both optional individually, but at least one is required — GithubClient throws InvalidTokenError otherwise. If both are set, auth takes precedence.

Both strategies implement the same GitHubAuth interface ({ getToken(): Promise<string> }), so you can switch between them — e.g. PAT locally, GitHub App in production — without changing any other code. PatAuth (also exported) wraps a token identically to passing token directly; use auth: new PatAuth(token) if you'd rather keep every strategy behind the same auth field.

Services

Each service is scoped to the owner/repo/org set on the client and exposed as a property:

ServiceAccessRequiresWhat it covers
Pull Requestsgithub.pullRequestsowner, repolist/get/create/update/merge, commits, files, reviews, cycleTime(), isMerged()
Repositoriesgithub.repositoriesowner, repo (some methods need org instead)get/update/delete, topics, tags, languages, contributors, security settings, org-scoped listing
Issuesgithub.issuesowner, repolist/get/create/update, comments
Releasesgithub.releasesowner, repolist/get/getLatest/getByTag/create/update/delete
Workflowsgithub.workflowsowner, repolist/get workflows, list/get/cancel/re-run runs, trigger dispatch
Organizationsgithub.organizationsorgget/update, listings, membership management
Usersgithub.usersauthenticated user, lookup by username/ID, list

There's no standalone commits service — list commits on a PR via github.pullRequests.listCommits(pullNumber).

Every public method has JSDoc with a runnable example — full signatures are in the source, e.g. PullRequestService.ts, RepositoryService.ts. For complete standalone scripts, see /examples.

Error handling

All non-2xx API responses throw typed errors instead of returning a raw error shape:

import{GithubApiError,InvalidTokenError,MissingConfigError,}from"@lujax/github-sdk";try{awaitgithub.pullRequests.get(9999);}catch(err){if(errinstanceofGithubApiError){console.error(err.status,err.message,err.documentationUrl);}}
  • GithubSdkError — base class for every error the SDK throws
  • GithubApiError — thrown on any non-ok GitHub API response; carries .status, .documentationUrl, and .details
  • InvalidTokenError — thrown when a GithubClient is constructed without token or auth
  • MissingConfigError — thrown when a service is constructed without the owner/repo/org it needs

HTTP behaviour

Built into every request, with no configuration needed:

  • Rate limiting — proactively waits out the reset window when x-ratelimit-remaining hits 0, instead of letting requests fail with a 403
  • Retries — 3 attempts with 1s/2s/4s backoff on 5xx and 429 responses
  • ETag caching — repeat GETs send If-None-Match; a 304 returns the cached body for free and doesn't count against your rate limit

Contributing

See CONTRIBUTING.md for setup, the module pattern, and the PR process. This project follows the Contributor Covenant Code of Conduct.

License

MIT

About

TypeScript-first GitHub REST API SDK - ergonomic, typed, near-zero dependencies

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Contributors

Languages