npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@treeviz/geni-sdk

v1.0.6

Published

Modern TypeScript SDK for Geni.com API - OAuth, Profiles API, World Family Tree, and genealogy utilities

Readme

@treeviz/geni-sdk

Part of the @treeviz organization - A collection of tools for genealogy data processing and visualization.

Modern TypeScript SDK for Geni.com API - OAuth, Profiles API, World Family Tree, and genealogy utilities.

Features

  • Full TypeScript Support - Comprehensive type definitions for all APIs
  • OAuth 2.0 Authentication - Complete OAuth flow with CSRF protection
  • Promise-based API - Modern async/await syntax
  • Rate Limiting - Built-in rate limiter (5,000 requests/day)
  • Modular Architecture - Use only what you need
  • Configurable Logging - Debug mode for troubleshooting
  • Error Handling - Comprehensive error classes

Installation

npm install @treeviz/geni-sdk

Quick Start

import { createGeniSDK } from '@treeviz/geni-sdk';

// Create SDK instance
const sdk = createGeniSDK({
  clientId: 'your-client-id',
  accessToken: 'your-oauth-token',
  debug: true
});

// Get current user profile
const profile = await sdk.profiles.getCurrentUser();
console.log('Current user:', profile.name);

// Search for profiles
const results = await sdk.search.searchProfiles({
  query: 'John Smith',
  birth_year: 1950,
  limit: 10
});
console.log('Found:', results.results.length, 'profiles');

OAuth Authentication

Client-Side Flow

import { OAuthAPI, buildAuthorizationUrl, validateOAuthState } from '@treeviz/geni-sdk/auth';

// 1. Build authorization URL and redirect user
const authUrl = buildAuthorizationUrl({
  clientId: 'your-client-id',
  redirectUri: 'https://your-app.com/callback',
  scope: 'read'
});
window.location.href = authUrl;

// 2. Handle OAuth callback (in your callback page)
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');

// Validate state (CSRF protection)
const validation = validateOAuthState(state);
if (!validation.valid) {
  console.error('OAuth state validation failed:', validation.error);
  return;
}

// 3. Exchange code for token (server-side only - requires client secret)
// This should be done in your backend/Cloud Function

Server-Side Token Exchange

import { exchangeCodeForToken } from '@treeviz/geni-sdk/auth';

const tokens = await exchangeCodeForToken(code, {
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret', // Never expose this in client code!
  redirectUri: 'https://your-app.com/callback'
});

console.log('Access token:', tokens.access_token);

API Modules

Profiles API

// Get current user
const user = await sdk.profiles.getCurrentUser();

// Get profile by ID
const profile = await sdk.profiles.getProfile('profile-123');

// Get immediate family
const family = await sdk.profiles.getImmediateFamily('profile-123');

// Get family tree (with depth)
const tree = await sdk.profiles.getTree('profile-123', 3);

// Update profile
const updated = await sdk.profiles.updateProfile('profile-123', {
  first_name: 'John',
  last_name: 'Doe'
});

// Search profiles
const results = await sdk.profiles.searchProfiles('John Smith');

Unions API (Marriages/Partnerships)

// Get union details
const union = await sdk.unions.getUnion('union-456');

// Get children of union
const children = await sdk.unions.getChildren('union-456');

// Create union
const newUnion = await sdk.unions.createUnion({
  partner1: 'profile-123',
  partner2: 'profile-456',
  status: 'married',
  marriage_date: '1980-06-15'
});

// Update union
const updated = await sdk.unions.updateUnion('union-456', {
  status: 'divorced',
  divorce_date: '2000-01-01'
});

// Delete union
await sdk.unions.deleteUnion('union-456');

Photos API

// Get photo details
const photo = await sdk.photos.getPhoto('photo-789');

// Upload photo
const newPhoto = await sdk.photos.uploadPhoto(
  'https://example.com/photo.jpg',
  'profile-123',
  'Birthday 1950'
);

// Delete photo
await sdk.photos.deletePhoto('photo-789');

Search API

// Basic search
const results = await sdk.search.searchProfiles({
  query: 'John Smith'
});

// Advanced search with filters
const filtered = await sdk.search.searchProfiles({
  query: 'John Smith',
  birth_year: 1950,
  death_year: 2020,
  location: 'New York',
  limit: 20
});

Rate Limiting

The SDK automatically enforces Geni's 5,000 requests/day limit:

// Check rate limit status
console.log(sdk.getRateLimitStatus());
// Output: "4995 / 5000 requests available"

// Get remaining requests
const remaining = sdk.getRemainingRequests();
console.log('Remaining requests:', remaining);

Error Handling

import { GeniError, GeniAuthError, GeniRateLimitError } from '@treeviz/geni-sdk';

try {
  const profile = await sdk.profiles.getProfile('invalid-id');
} catch (error) {
  if (error instanceof GeniAuthError) {
    console.error('Authentication failed:', error.message);
  } else if (error instanceof GeniRateLimitError) {
    console.error('Rate limit exceeded. Retry after:', error.retryAfter, 'seconds');
  } else if (error instanceof GeniError) {
    console.error('Geni API error:', error.message, error.statusCode);
  } else {
    console.error('Unknown error:', error);
  }
}

Configuration

const sdk = createGeniSDK({
  // Required
  clientId: 'your-client-id',
  
  // Optional
  appKey: 'your-app-key', // Usually same as clientId
  accessToken: 'your-oauth-token',
  debug: false, // Enable debug logging
  logger: customLogger, // Custom logger implementation
  rateLimiter: {
    enabled: true,
    maxRequestsPerDay: 5000
  }
});

Singleton Pattern

import { initGeniSDK, getGeniSDK } from '@treeviz/geni-sdk';

// Initialize once
initGeniSDK({
  clientId: 'your-client-id',
  accessToken: 'your-oauth-token'
});

// Use anywhere
const sdk = getGeniSDK();
const profile = await sdk.profiles.getCurrentUser();

TypeScript Support

All types are exported for your convenience:

import type {
  GeniProfile,
  GeniUnionDetail,
  GeniOAuthConfig,
  ProfileSearchResponse,
  ImmediateFamilyResponse
} from '@treeviz/geni-sdk';

License

MIT

Contributing

Contributions are welcome! Please read our contributing guidelines.

Links