Kysely
The Kysely packages provide storage implementations using the Kysely query builder, giving you type-safe SQL across multiple databases.
| Package | Database | Driver |
|---|---|---|
@pikku/kysely | PostgreSQL | postgres.js via kysely-postgres-js |
@pikku/kysely-mysql | MySQL | mysql2 via kysely |
@pikku/kysely-sqlite | SQLite | better-sqlite3 via kysely |
All three packages export the same service interfaces β choose the one matching your database.
Installationβ
PostgreSQL:
npm install @pikku/kysely kysely kysely-postgres-js postgres
MySQL:
npm install @pikku/kysely-mysql kysely mysql2
SQLite:
npm install @pikku/kysely-sqlite kysely better-sqlite3
Servicesβ
PikkuKyselyβ
Connection manager and database abstraction. All other Kysely services require an instance of this.
import { PikkuKysely } from '@pikku/kysely'
import postgres from 'postgres'
const sql = postgres(process.env.DATABASE_URL!)
const db = new PikkuKysely(logger, sql)
await db.init()
Constructor: new PikkuKysely(logger, connectionOrConfig, defaultSchemaName?)
| Parameter | Type | Default | Description |
|---|---|---|---|
logger | Logger | β | Pikku logger instance |
connectionOrConfig | postgres.Sql | postgres.Options | β | Postgres connection or config |
defaultSchemaName | string | β | Default schema for table creation |
KyselyAIStorageServiceβ
Implements both AIStorageService and AIRunStateService for AI Agent persistence.
import { KyselyAIStorageService } from '@pikku/kysely'
const aiStorage = new KyselyAIStorageService(db.kysely)
await aiStorage.init()
Provides the same methods as PgAIStorageService.
KyselyAgentRunServiceβ
Read-only agent run queries for the Console.
import { KyselyAgentRunService } from '@pikku/kysely'
const agentRunService = new KyselyAgentRunService(db.kysely)
KyselyWorkflowServiceβ
Workflow orchestration with Kysely.
import { KyselyWorkflowService } from '@pikku/kysely'
const workflowService = new KyselyWorkflowService(db.kysely)
await workflowService.init()
KyselyWorkflowRunServiceβ
Read-only workflow run queries for the Console.
import { KyselyWorkflowRunService } from '@pikku/kysely'
const workflowRunService = new KyselyWorkflowRunService(db.kysely)
KyselyChannelStoreβ
WebSocket channel and subscription persistence.
import { KyselyChannelStore } from '@pikku/kysely'
const channelStore = new KyselyChannelStore(db.kysely)
await channelStore.init()
KyselyDeploymentServiceβ
Multi-instance deployment tracking.
import { KyselyDeploymentService } from '@pikku/kysely'
const deploymentService = new KyselyDeploymentService(config, db.kysely)
await deploymentService.init()
KyselySecretServiceβ
Encrypted secret storage with envelope encryption and key rotation.
import { KyselySecretService } from '@pikku/kysely'
const secrets = new KyselySecretService(db.kysely, {
key: process.env.ENCRYPTION_KEY!,
keyVersion: 1,
})
await secrets.init()
KyselyCredentialServiceβ
Per-user credential storage.
import { KyselyCredentialService } from '@pikku/kysely'
const credentialService = new KyselyCredentialService(db.kysely, {
key: process.env.ENCRYPTION_KEY!,
})
await credentialService.init()
KyselyEventHubStoreβ
Channel topic subscription tracking.
import { KyselyEventHubStore } from '@pikku/kysely'
const eventHubStore = new KyselyEventHubStore(db.kysely)
await eventHubStore.init()
Type-Safe Queriesβ
The KyselyPikkuDB type provides full type safety for direct Kysely queries against Pikku tables:
import type { KyselyPikkuDB } from '@pikku/kysely'
import type { Kysely } from 'kysely'
async function customQuery(db: Kysely<KyselyPikkuDB>) {
return db
.selectFrom('aiThreads')
.where('resourceId', '=', 'user-123')
.selectAll()
.execute()
}
Full Exampleβ
import {
PikkuKysely,
KyselyAIStorageService,
KyselyAgentRunService,
KyselyWorkflowService,
} from '@pikku/kysely'
import { VercelAIAgentRunner } from '@pikku/ai-vercel'
import { createOpenAI } from '@ai-sdk/openai'
import postgres from 'postgres'
const sql = postgres(process.env.DATABASE_URL!)
const db = new PikkuKysely(logger, sql)
await db.init()
const aiStorage = new KyselyAIStorageService(db.kysely)
await aiStorage.init()
const workflowService = new KyselyWorkflowService(db.kysely)
await workflowService.init()
const singletonServices = await createSingletonServices(config, {
aiStorage,
aiRunState: aiStorage,
agentRunService: new KyselyAgentRunService(db.kysely),
workflowService,
aiAgentRunner: new VercelAIAgentRunner({
openai: createOpenAI({ apiKey: process.env.OPENAI_API_KEY! }),
}),
})
MySQL (@pikku/kysely-mysql)β
All services from @pikku/kysely have MySQL equivalents with the MySQL prefix:
import {
MySQLKyselyAIStorageService,
MySQLKyselyAgentRunService,
MySQLKyselyWorkflowService,
MySQLKyselyWorkflowRunService,
MySQLKyselyChannelStore,
MySQLKyselyEventHubStore,
MySQLKyselyDeploymentService,
MySQLKyselySecretService,
} from '@pikku/kysely-mysql'
Usage is identical to the PostgreSQL versions β pass a Kysely<KyselyPikkuDB> instance backed by a MySQL dialect.
SQLite (@pikku/kysely-sqlite)β
All services have SQLite equivalents with the SQLite prefix. The package also provides a helper for creating the Kysely instance:
import { createSQLiteKysely } from '@pikku/kysely-sqlite'
import {
SQLiteKyselyAIStorageService,
SQLiteKyselyAgentRunService,
SQLiteKyselyWorkflowService,
SQLiteKyselyWorkflowRunService,
SQLiteKyselyChannelStore,
SQLiteKyselyEventHubStore,
SQLiteKyselyDeploymentService,
SQLiteKyselySecretService,
} from '@pikku/kysely-sqlite'
const db = createSQLiteKysely('./pikku.db')
const aiStorage = new SQLiteKyselyAIStorageService(db)
await aiStorage.init()
SQLite is used by the Cloudflare D1 integration (@pikku/cloudflare/d1) under the hood.
Cleanupβ
await db.close()
await sql.end()