Library Development Skill
Best practices for developing and publishing TypeScript libraries.
API Design Principles
1. Simple Entry Point
typescript
// ✅ Good - one clear entry
import { createSheetsDB } from 'gas-sheets-query'
const db = createSheetsDB({ ... })
// ❌ Bad - confusing imports
import { SheetsDB, QueryBuilder, Repository, ... } from 'gas-sheets-query'
2. Fluent API (Method Chaining)
typescript
// ✅ Readable, discoverable
db.from('users')
.where('status', '=', 'active')
.orderBy('name')
.limit(10)
.exec()
3. Sensible Defaults
typescript
// Works with minimal config
const db = createSheetsDB({ tables: { users: {} } })
// But allows customization
const db = createSheetsDB({
spreadsheetId: 'xxx',
tables: { users: { columns: [...], indexes: [...] } },
options: { cacheEnabled: true }
})
Type Safety
Generic Inference
typescript
// Schema defines types
const db = createSheetsDB({
tables: {
users: {
columns: ['id', 'name', 'email'] as const,
types: {} as { id: string; name: string; email: string }
}
}
})
// Auto-complete works
db.from('users').where('name', '=', 'John') // ✅ 'name' is typed
db.from('users').where('foo', '=', 'x') // ❌ Error: 'foo' not in users
Testing Strategy
Unit Tests
- •Test each function in isolation
- •Mock external dependencies (Sheets API)
Integration Tests
- •Test with real Sheets (separate test spreadsheet)
- •Run in CI with service account
Example Test Structure
code
tests/
├── unit/
│ ├── query-builder.test.ts
│ └── repository.test.ts
├── integration/
│ └── gas-adapter.test.ts
└── fixtures/
└── test-data.ts
Versioning & Release
Semantic Versioning
- •MAJOR: Breaking API changes
- •MINOR: New features (backward compatible)
- •PATCH: Bug fixes
Release Checklist
- •Update CHANGELOG.md
- •Run full test suite
- •Bump version:
pnpm version [major|minor|patch] - •Build:
pnpm build - •Publish:
npm publish - •Create GitHub release with tag
Documentation
README Structure
- •One-liner description
- •Installation
- •Quick start (copy-paste example)
- •API reference
- •Advanced usage
- •Contributing
JSDoc for Public APIs
typescript
/**
* Create a query builder for the specified table.
*
* @param table - Table name defined in schema
* @returns QueryBuilder instance for chaining
*
* @example
* ```ts
* db.from('users').where('active', '=', true).exec()
* ```
*/
from<T extends keyof Tables>(table: T): QueryBuilder<Tables[T]>
Error Handling
Descriptive Errors
typescript
// ✅ Good
throw new Error(`Table "${table}" not found. Available: ${Object.keys(tables).join(', ')}`)
// ❌ Bad
throw new Error('Invalid table')
Error Types
typescript
export class SheetsQueryError extends Error {
constructor(message: string, public code: string) {
super(message)
this.name = 'SheetsQueryError'
}
}
export class TableNotFoundError extends SheetsQueryError {
constructor(table: string) {
super(`Table "${table}" not found`, 'TABLE_NOT_FOUND')
}
}
References
- •references/api-patterns.md - Common API patterns
- •references/npm-publish.md - npm publishing guide