lsbible
v0.3.0
Published
LSBible API client - structured, type-safe Bible SDK for TypeScript
Maintainers
Readme
LSBible SDK for TypeScript
Structured, type-safe Bible API client for the Legacy Standard Bible (LSB).
Features
- 100% Type-Safe - Full TypeScript support with Zod validation
- Structured Parameters - No string parsing! Use
client.getVerse(BookName.JOHN, 3, 16) - Complete Validation - All 66 books with chapter/verse validation
- Rich Formatting - Preserves red-letter text, italics, bold, small-caps
- Built-in Caching - Configurable TTL-based response cache
- Modern Runtime Support - Works with Node.js 18+, Bun, and Deno
Installation
# Using npm
npm install lsbible
# Using pnpm
pnpm add lsbible
# Using bun
bun add lsbibleMCP Server
This SDK also includes a Model Context Protocol (MCP) server for integration with AI coding assistants like Cursor, Claude Code, VS Code, and more.
🤖 For MCP Server Installation: To use LSBible with AI coding tools, see the MCP Installation Guide → with step-by-step instructions for 20+ supported clients.
Quick Install Examples:
# Claude Code (remote)
claude mcp add --transport http lsbible https://lsbible.kdco.dev/mcp
# Claude Code (local)
claude mcp add lsbible -- npx -y lsbible-mcp
# Cursor/VS Code/etc. (see full guide)
# Add to your MCP config file - see mcp/README.md for detailsQuick Start
import { LSBibleClient, BookName } from "lsbible";
const client = new LSBibleClient();
// Get a single verse (type-safe with enum)
const verse = await client.getVerse(BookName.JOHN, 3, 16);
console.log(verse.verses[0].plainText);
// Output: "For God so loved the world, that He gave His only Son..."
// Get a passage range
const passage = await client.getPassage(
BookName.JOHN, 3, 16,
BookName.JOHN, 3, 18
);
console.log(`Got ${passage.verseCount} verses`);
// Get an entire chapter
const chapter = await client.getChapter(BookName.PSALMS, 23);
console.log(`Psalm 23 has ${chapter.verseCount} verses`);
// Search for text
const results = await client.search("love");
console.log(`Found ${results.matchCount} matches in ${results.passageCount} passages`);Design Philosophy
Structured Parameters Over String Parsing
This SDK prioritizes explicit, structured parameters over string-based references:
// ✅ GOOD - Structured, type-safe, validated
client.getVerse(BookName.JOHN, 3, 16);
// ❌ AVOID - String parsing (error-prone, less type-safe)
client.getVerse("John 3:16"); // NOT SUPPORTEDWhy Structured Parameters?
- Type Safety - IDE autocomplete for all 66 books
- Early Validation - Catch errors before API calls
- No Parsing Ambiguity - Clear, explicit parameters
- Better Testing - Easy to generate test cases programmatically
- Language Agnostic - Works consistently across all SDKs
API Reference
LSBibleClient
import { LSBibleClient, MemoryCacheProvider } from "lsbible";
const client = new LSBibleClient({
cache: {
provider: new MemoryCacheProvider(), // Optional cache provider
ttl: {
verse: 2592000, // 30 days (default)
passage: 2592000, // 30 days (default)
chapter: 2592000, // 30 days (default)
search: 604800, // 7 days (default)
}
},
timeout: 30, // Request timeout in seconds (default: 30)
buildId: undefined, // Optional build ID (auto-detected if not provided)
headers: {}, // Optional custom headers
});Methods
getVerse(book, chapter, verse)
Get a specific verse with validated parameters.
// Using enum (recommended)
const verse = await client.getVerse(BookName.JOHN, 3, 16);
// Using string (validated at runtime)
const verse = await client.getVerse("John", 3, 16);
// Access structured data
for (const v of verse.verses) {
console.log(`${v.reference.toString()}: ${v.plainText}`);
// Access formatting
for (const segment of v.segments) {
if (segment.isRedLetter) {
console.log(`Jesus said: "${segment.text}"`);
}
}
}getPassage(fromBook, fromChapter, fromVerse, toBook, toChapter, toVerse)
Get a passage spanning multiple verses.
// Get John 3:16-18
const passage = await client.getPassage(
BookName.JOHN, 3, 16,
BookName.JOHN, 3, 18
);
console.log(`Title: ${passage.title}`);
console.log(`Verses: ${passage.verseCount}`);
console.log(`Single verse? ${passage.isSingleVerse}`);getChapter(book, chapter)
Get an entire chapter.
// Get all of Psalm 23
const chapter = await client.getChapter(BookName.PSALMS, 23);
console.log(`Psalm 23 has ${chapter.verseCount} verses`);
for (const verse of chapter.verses) {
console.log(` ${verse.verseNumber}. ${verse.plainText}`);
}search(query)
Search for passages containing text.
const results = await client.search("love");
console.log(`Found ${results.matchCount} matches`);
console.log(`Passages: ${results.passageCount}`);
console.log(`Total verses: ${results.totalVerses}`);
// Search results include metadata (for text searches)
if (results.hasSearchMetadata) {
console.log(`Total results: ${results.totalCount}`);
console.log(`Filtered: ${results.filteredCount}`);
console.log(`By book:`, results.countsByBook);
}
// Iterate through results
for (const passage of results.passages) {
console.log(`\n${passage.title}`);
for (const verse of passage.verses) {
console.log(` ${verse.plainText}`);
}
}clearCache()
Clear the response cache (only available with MemoryCacheProvider).
client.clearCache();Caching
The SDK supports pluggable caching through the CacheProvider interface, allowing you to choose the right caching strategy for your deployment environment.
Built-in Cache Providers
MemoryCacheProvider - In-memory caching with TTL support
- ✅ Local development, testing, single-process apps
- ❌ Multi-process apps, Cloudflare Workers, high-traffic production
NoopCacheProvider - Disables caching entirely
- Useful for debugging or when caching isn't beneficial
CloudflareCacheProvider - Edge caching for Cloudflare Workers
- Available in the MCP Server implementation
Cache Configuration
import { LSBibleClient, MemoryCacheProvider, CacheTTL } from "lsbible";
const client = new LSBibleClient({
cache: {
provider: new MemoryCacheProvider(),
ttl: {
verse: CacheTTL.BIBLE_CONTENT, // 30 days
passage: CacheTTL.BIBLE_CONTENT, // 30 days
chapter: CacheTTL.BIBLE_CONTENT, // 30 days
search: CacheTTL.SEARCH_RESULTS, // 7 days
}
}
});Recommended TTL constants:
CacheTTL.BIBLE_CONTENT(30 days) - Bible text is immutableCacheTTL.SEARCH_RESULTS(7 days) - May change with API updatesCacheTTL.STATIC(1 year) - Never changes
Custom Cache Providers
Implement the CacheProvider interface for custom backends like Redis, Memcached, or DynamoDB:
interface CacheProvider {
get<T>(key: string): Promise<T | undefined>;
set<T>(key: string, value: T, ttl: number): Promise<void>;
}Complete examples:
- Memory Cache - Demonstrates cache hits/misses and manual clearing
- Redis Cache - Full Redis implementation with ioredis
- Custom Cache - Template for building your own cache provider
Cache Keys
The SDK uses these cache key patterns:
verse:{book} {chapter}:{verse}- Single versespassage:{normalized query}- Passage rangeschapter:{book} {chapter}- Full chapterssearch:{query}- Text searches
Type System
BookName Enum
All 66 Bible books available as enum values:
import { BookName } from "lsbible";
// Old Testament
BookName.GENESIS
BookName.EXODUS
// ... through ...
BookName.MALACHI
// New Testament
BookName.MATTHEW
BookName.MARK
// ... through ...
BookName.REVELATIONVerseReference
interface VerseReference {
bookNumber: number; // 1-66
chapter: number; // Validated against book
verse: number; // Validated against chapter
readonly bookName: BookName; // Computed property
toString(): string; // e.g., "John 3:16"
}TextSegment
interface TextSegment {
text: string;
isRedLetter: boolean; // Words of Jesus
isItalic: boolean; // Italicized clarifications
isBold: boolean; // Bold text
isSmallCaps: boolean; // LORD (Yahweh)
}VerseContent
interface VerseContent {
reference: VerseReference;
verseNumber: number;
segments: TextSegment[];
hasSubheading: boolean;
subheadingText: string | null;
isPoetry: boolean;
isProse: boolean;
chapterStart: boolean;
readonly plainText: string; // Computed property
readonly formattedText: string; // Computed property
}Passage
interface Passage {
fromRef: VerseReference;
toRef: VerseReference;
title: string;
verses: VerseContent[];
readonly isSingleVerse: boolean; // Computed property
readonly verseCount: number; // Computed property
}SearchResponse
interface SearchResponse {
query: string;
matchCount: number;
passages: Passage[];
durationMs: number;
timestamp: number;
// Optional (for text searches only)
totalCount?: number;
filteredCount?: number;
countsByBook?: Record<string, number>;
countsBySection?: Record<string, number>;
// Computed properties
readonly passageCount: number;
readonly totalVerses: number;
readonly hasSearchMetadata: boolean;
}Error Handling
import { LSBibleClient, BookName, InvalidReferenceError, APIError } from "lsbible";
const client = new LSBibleClient();
try {
// Invalid chapter (John only has 21 chapters)
await client.getVerse(BookName.JOHN, 99, 1);
} catch (error) {
if (error instanceof InvalidReferenceError) {
console.error(`Invalid reference: ${error.message}`);
// Output: "John only has 21 chapters, but chapter 99 was requested"
}
}
try {
// Invalid verse (John 3 only has 36 verses)
await client.getVerse(BookName.JOHN, 3, 999);
} catch (error) {
if (error instanceof InvalidReferenceError) {
console.error(`Invalid reference: ${error.message}`);
// Output: "John 3 only has 36 verses, but verse 999 was requested"
}
}
try {
// Invalid book name
await client.getVerse("NotABook", 1, 1);
} catch (error) {
if (error instanceof InvalidReferenceError) {
console.error(`Invalid reference: ${error.message}`);
// Output: "Unknown book: NotABook"
}
}
try {
// API failure
await client.search("something");
} catch (error) {
if (error instanceof APIError) {
console.error(`API error: ${error.message}`);
}
}Bible Structure Data
The SDK includes complete validation data for all 66 books:
- Old Testament: 39 books (Genesis through Malachi)
- New Testament: 27 books (Matthew through Revelation)
- Total: 1,189 chapters, 31,102 verses
import { BIBLE_STRUCTURE, BOOK_NAMES, BOOK_NUMBERS } from "lsbible";
// Get book info
const johnInfo = BIBLE_STRUCTURE[43];
console.log(johnInfo.name); // "John"
console.log(johnInfo.chapters); // 21
console.log(johnInfo.verses[2]); // Chapter 3 has 36 verses
// Lookup book number
const bookNum = BOOK_NUMBERS["john"]; // 43
// Lookup book name
const bookName = BOOK_NAMES[43]; // "John"Runtime Support
The SDK is designed to work across modern JavaScript runtimes:
- Node.js 18.0.0 or higher (native fetch support)
- Bun (optimized build performance)
- Deno (works out of the box)
Examples
Example 1: Display a Verse with Formatting
import { LSBibleClient, BookName } from "lsbible";
const client = new LSBibleClient();
const verse = await client.getVerse(BookName.JOHN, 3, 16);
for (const v of verse.verses) {
console.log(`\n${v.reference.toString()}\n`);
for (const segment of v.segments) {
let text = segment.text;
if (segment.isRedLetter) text = `\x1b[31m${text}\x1b[0m`; // Red
if (segment.isItalic) text = `\x1b[3m${text}\x1b[0m`; // Italic
if (segment.isSmallCaps) text = text.toUpperCase(); // Small caps -> uppercase
process.stdout.write(text + " ");
}
console.log("\n");
}Example 2: Find All Occurrences of a Word
import { LSBibleClient } from "lsbible";
const client = new LSBibleClient();
const results = await client.search("faith");
console.log(`Found "${results.query}" ${results.matchCount} times\n`);
for (const passage of results.passages) {
for (const verse of passage.verses) {
console.log(`${verse.reference.toString()}: ${verse.plainText}`);
}
}Example 3: Read an Entire Book
import { LSBibleClient, BookName, BIBLE_STRUCTURE } from "lsbible";
const client = new LSBibleClient();
const bookNum = 57; // Philemon
const bookInfo = BIBLE_STRUCTURE[bookNum];
console.log(`Reading ${bookInfo.name}\n`);
for (let chapter = 1; chapter <= bookInfo.chapters; chapter++) {
const passage = await client.getChapter(BookName.PHILEMON, chapter);
console.log(`\nChapter ${chapter}\n`);
for (const verse of passage.verses) {
console.log(`${verse.verseNumber}. ${verse.plainText}`);
}
}Contributing
This SDK is part of the LSBible monorepo. Contributions are welcome!
See the main repository for contribution guidelines: https://github.com/kdcokenny/lsbible
License
MIT License - See LICENSE file for details.
Related
- Python SDK - Official Python implementation
- API Documentation - Complete SDK specification
- LSBible Website - Read the Legacy Standard Bible online
