Shared database adapter system for building useful backend libraries
npm install @superfunctions/dbShared database adapter system for Superfunctions libraries. Provides a unified interface for interacting with databases across multiple ORMs (Drizzle, Prisma, Kysely).
``bash
npm install @superfunctions/db
Quick Start
$3
`typescript
import { AuthFn } from '@superfunctions/authFn';
import { memoryAdapter } from '@superfunctions/db/adapters';// Create adapter
const adapter = memoryAdapter({
namespace: { enabled: true }
});
// Initialize library with adapter
const authFn = AuthFn({
database: adapter,
namespace: 'authFn'
});
// Use the library
await authFn.createUser({
email: 'user@example.com',
password: 'password',
name: 'John Doe',
});
`Core Concepts
$3
All adapters implement a unified interface:
`typescript
interface Adapter {
// CRUD operations
create(params: CreateParams): Promise;
findOne(params: FindOneParams): Promise;
findMany(params: FindManyParams): Promise;
update(params: UpdateParams): Promise;
delete(params: DeleteParams): Promise;
// Batch operations
createMany(params: CreateManyParams): Promise;
updateMany(params: UpdateManyParams): Promise;
deleteMany(params: DeleteManyParams): Promise;
// Advanced
upsert(params: UpsertParams): Promise;
count(params: CountParams): Promise;
transaction(callback: (trx: TransactionAdapter) => Promise): Promise;
// Lifecycle
initialize(): Promise;
isHealthy(): Promise;
close(): Promise;
// Schema management
getSchemaVersion(namespace: string): Promise;
setSchemaVersion(namespace: string, version: number): Promise;
}
`$3
Adapters declare their capabilities, and libraries adapt accordingly:
`typescript
const adapter = memoryAdapter();if (adapter.capabilities.operations.batch) {
// Use batch operations
await adapter.createMany({ model: 'users', data: users });
} else {
// Fallback to sequential
for (const user of users) {
await adapter.create({ model: 'users', data: user });
}
}
`$3
Prevent table name conflicts when multiple libraries use the same database:
`typescript
const adapter = memoryAdapter({
namespace: {
enabled: true,
separator: '_'
}
});// Library A
const authFn = AuthFn({ database: adapter, namespace: 'authFn' });
// Tables: authFn_users, authFn_sessions, authFn_tokens
// Library B
const fileFn = FileFn({ database: adapter, namespace: 'fileFn' });
// Tables: fileFn_files, fileFn_folders
// No conflicts!
`Built-in Adapters
$3
In-memory adapter for testing and development:
`typescript
import { memoryAdapter } from '@superfunctions/db/adapters';const adapter = memoryAdapter({
namespace: { enabled: true },
debug: true
});
`$3
For Drizzle ORM (PostgreSQL, MySQL, SQLite):
`typescript
import { drizzle } from 'drizzle-orm/node-postgres';
import { users, posts } from './schema';
import { drizzleAdapter } from '@superfunctions/db/adapters';const db = drizzle(pool);
const adapter = drizzleAdapter({
db,
dialect: 'postgres', // 'postgres' | 'mysql' | 'sqlite'
schema: { users, posts }, // model name → drizzle table
upsertKeys: { users: 'email' }, // conflict targets
schemaVersionsTable, // optional
debug: false
});
`Features:
- Full CRUD with where/orderBy/select
- Batch operations
- Transactions (async for Postgres/MySQL)
- Upsert with conflict resolution
- All where operators: eq, ne, gt, gte, lt, lte, in, not_in, contains, starts_with, ends_with
$3
For Prisma ORM:
`typescript
import { PrismaClient } from '@prisma/client';
import { prismaAdapter } from '@superfunctions/db/adapters';const prisma = new PrismaClient();
const adapter = prismaAdapter({
prisma,
modelMap: { users: 'user', posts: 'post' }, // model → Prisma model name
schemaVersionsTable: 'schemaVersions', // optional
debug: false
});
`Features:
- Full where clause translation with AND/OR
- Select projection and orderBy
- Batch operations
- Transaction support via
$transaction
- Upsert with unique constraints$3
For Kysely query builder:
`typescript
import { Kysely, PostgresDialect } from 'kysely';
import { kyselyAdapter } from '@superfunctions/db/adapters';const db = new Kysely({
dialect: new PostgresDialect({ pool })
});
const adapter = kyselyAdapter({
db,
dialect: 'postgres', // 'postgres' | 'mysql' | 'sqlite'
schema: { users: 'users', posts: 'posts' }, // model → table name
schemaVersionsTable: '__schema_versions', // optional
debug: false
});
`Features:
- Type-safe query building
- Full CRUD with all operators
- Transactions
- Upsert (INSERT...ON CONFLICT)
- Multi-dialect support
Testing
Use the built-in memory adapter for testing:
`typescript
import { memoryAdapter } from '@superfunctions/db/testing';
import { describe, it, expect } from 'vitest';describe('My Library', () => {
it('should create records', async () => {
const adapter = memoryAdapter();
const result = await adapter.create({
model: 'users',
data: { name: 'John' }
});
expect(result).toHaveProperty('id');
expect(result.name).toBe('John');
});
});
`TypeScript
Full TypeScript support with strict types:
`typescript
import type {
Adapter,
CreateParams,
WhereClause,
TableSchema
} from '@superfunctions/db';const adapter: Adapter = memoryAdapter();
const params: CreateParams = {
model: 'users',
data: { name: 'John' }
};
const user = await adapter.create(params);
`Error Handling
Standardized error classes across all adapters:
`typescript
import {
AdapterError,
NotFoundError,
ConnectionError
} from '@superfunctions/db';try {
await adapter.findOne({ model: 'users', where: [{ field: 'id', operator: 'eq', value: '123' }] });
} catch (error) {
if (error instanceof NotFoundError) {
console.log('User not found');
} else if (error instanceof ConnectionError) {
console.log('Database connection failed');
} else if (error instanceof AdapterError) {
console.log('Adapter error:', error.code);
}
}
`License
Apache-2.0
Contributing
Contributions welcome! See Contributing Guide for details.
Related Packages
-
@superfunctions/cli` - Schema management and migrations