Lockness Architecture
Understanding Lockness modular architecture and package system.
Core Philosophy
Lockness follows a minimal core, optional features approach:
- @lockness/core - Essential framework only (App, DI, Hono)
- Optional packages - Import explicitly when needed
Bootstrap Pipeline
The kernel loader uses a modular bootstrap step architecture to initialize
your application. When you call createApp(KernelClass), the following steps
execute in sequence:
- Database (100) - Database connection
- Session (110) - Session configuration
- Cache (120) - Cache system setup
- App Creation (200) - Create App instance
- Devtools (210) - Enable devtools (development only)
- Middleware (300) - Register global middlewares
- Boot Hooks (310) - Execute
@OnBootmethods - Middleware Discovery (400) - Auto-discover named middlewares
- Listener Registration (410) - Register event listeners
- Events (500) - Emit KernelBooted event
- App Initialization (550) - Initialize controllers and static files
- Devtools Routes (600) - Collect routes for devtools
Benefits:
- ✅ Predictable initialization order
- ✅ Each step isolated and testable
- ✅ Optional packages loaded gracefully
- ✅ Extensible without modifying core
See Kernel Lifecycle for details.
Package System
Core Package (@lockness/core)
Always required. Includes:
- Framework fundamentals (App, routing, decorators)
- Dependency Injection system
- Complete Hono integration (all middleware & utilities)
- JSX runtime and components
import {
App, // Framework core
basicAuth,
cache,
Controller, // Decorators
cors,
Get,
Inject,
jwt,
logger, // Hono middleware
Post,
Service, // DI system
validator,
// ... all Hono exports
} from '@lockness/core'
What's NOT in core:
- Sessions (optional for APIs)
- Queue system (optional feature)
- Cache system (separate from Hono cache middleware)
- Logger system (separate from Hono logger middleware)
- Mail, Storage, Socialite, etc.
Optional Packages
Import explicitly when needed:
@lockness/session
For: Traditional web apps with session-based auth Skip if: Building stateless JWT APIs
// In your kernel
import { sessionMiddleware } from '@lockness/session'
@Kernel({
session: {
driver: 'cookie',
secret: Deno.env.get('SESSION_SECRET')!,
lifetime: 7200,
},
})
export class AppKernel {
@DeclareGlobalMiddleware()
globalMiddlewares = [
sessionMiddleware(),
]
}
@lockness/queue
For: Background job processing (emails, exports, etc.) Skip if: No background tasks needed
import { configureQueue, Job, registerJob } from '@lockness/queue'
class SendEmailJob extends Job {
async handle() {
// Send email
}
}
registerJob('send-email', SendEmailJob)
@lockness/cache
For: Application-level caching system Different from: Hono's HTTP cache middleware (in core)
import { cache, configureCache } from '@lockness/cache'
configureCache({ driver: 'deno-kv' })
// Cache data
await cache.remember('user:1', () => fetchUser(1), 3600)
@lockness/logger
For: Structured logging system with transports Different from: Hono's HTTP logger middleware (in core)
import { ConsoleTransport, Logger } from '@lockness/logger'
const logger = new Logger()
logger.addTransport(new ConsoleTransport())
logger.info('User logged in', { userId: 123 })
@lockness/auth
For: Authentication with guards and providers Requires: Usually needs @lockness/session for web apps
import { initializeAuthMiddleware, SessionGuard } from '@lockness/auth'
import { sessionMiddleware } from '@lockness/session'
import { UserProvider } from './auth/user_provider.ts'
@Kernel({
session: { driver: 'cookie', secret: 'your-secret' },
})
export class AppKernel {
@DeclareGlobalMiddleware()
globalMiddlewares = [
sessionMiddleware(),
initializeAuthMiddleware({
default: 'web',
guards: {
web: (ctx) => new SessionGuard('web', ctx, new UserProvider()),
},
}),
]
}
Architecture Benefits
1. Lightweight APIs
// Minimal JWT API (no sessions, no queue)
import { createApp, jwt, Kernel } from '@lockness/core'
@Kernel({
staticDir: 'public',
controllersDir: './app/controller',
})
export class AppKernel {
@DeclareGlobalMiddleware()
globalMiddlewares = [
jwt({ secret: 'your-secret' }),
]
}
const app = await createApp(AppKernel)
Bundle includes: Only core + Hono (~2MB) Excludes: Session, queue, cache systems (unused code)
2. Full Web App
// Traditional web app with all features
import { createApp, DeclareGlobalMiddleware, Kernel } from '@lockness/core'
import { sessionMiddleware } from '@lockness/session'
import { configureQueue } from '@lockness/queue'
import { configureCache } from '@lockness/cache'
@Kernel({
database: { url: Deno.env.get('DATABASE_URL') },
session: { driver: 'cookie', secret: 'secret' },
devtools: true,
controllersDir: './app/controller',
})
export class AppKernel {
@DeclareGlobalMiddleware()
globalMiddlewares = [
sessionMiddleware(),
]
}
// Configure optional features
configureQueue({ driver: 'deno-kv' })
configureCache({ driver: 'memory' })
const app = await createApp(AppKernel)
Bundle includes: Core + selected features Explicit: Clear what dependencies are used
3. Zero Naming Conflicts
Hono middleware keeps original names:
import {
cache, // Hono HTTP cache middleware
logger, // Hono HTTP logger middleware
validator, // Hono request validator
} from '@lockness/core'
// Separate packages if needed:
import { cache as cacheSystem } from '@lockness/cache'
import { Logger } from '@lockness/logger'
import { Validator } from '@lockness/validator'
Project Examples
Minimal API (JWT only)
Dependencies:
- @lockness/core
Setup:
import { createApp, DeclareGlobalMiddleware, jwt, Kernel } from '@lockness/core'
@Kernel({ controllersDir: './app/controller' })
export class AppKernel {
@DeclareGlobalMiddleware()
globalMiddlewares = [jwt({ secret: 'secret' })]
}
const app = await createApp(AppKernel)
Traditional Web App
Dependencies:
- @lockness/core
- @lockness/session
- @lockness/auth
Setup:
import { createApp, DeclareGlobalMiddleware, Kernel } from '@lockness/core'
import { sessionMiddleware } from '@lockness/session'
import { initializeAuthMiddleware } from '@lockness/auth'
@Kernel({
session: { driver: 'cookie', secret: 'secret' },
controllersDir: './app/controller',
})
export class AppKernel {
@DeclareGlobalMiddleware()
globalMiddlewares = [
sessionMiddleware(),
initializeAuthMiddleware({/* ... */}),
]
}
const app = await createApp(AppKernel)
Full-Featured SaaS
Dependencies:
- @lockness/core
- @lockness/session
- @lockness/auth
- @lockness/queue
- @lockness/cache
- @lockness/mail
- @lockness/storage
Setup:
import {
createApp,
DeclareGlobalMiddleware,
Kernel,
OnBoot,
} from '@lockness/core'
import { sessionMiddleware } from '@lockness/session'
import { configureQueue } from '@lockness/queue'
import { configureCache } from '@lockness/cache'
import { configureMail } from '@lockness/mail'
import { configureStorage } from '@lockness/storage'
@Kernel({
database: { url: Deno.env.get('DATABASE_URL') },
session: { driver: 'cookie', secret: 'secret', lifetime: 7200 },
devtools: true,
controllersDir: './app/controller',
middlewaresDir: './app/middleware',
})
export class AppKernel {
@DeclareGlobalMiddleware()
globalMiddlewares = [
sessionMiddleware(),
// ... other middlewares
]
@OnBoot({ priority: 100 })
async configureServices() {
configureQueue({/* ... */})
configureCache({/* ... */})
configureMail({/* ... */})
configureStorage({/* ... */})
}
}
const app = await createApp(AppKernel)
Migration Guide
If you have existing code importing from @lockness/core:
Sessions
// ❌ Old (imperative style)
import { configureSession, sessionMiddleware } from '@lockness/session'
configureSession({ driver: 'cookie', secret: 'secret' })
app.useMiddleware(sessionMiddleware())
// ✅ New (declarative with @Kernel)
import { sessionMiddleware } from '@lockness/session'
@Kernel({
session: { driver: 'cookie', secret: 'secret' },
})
export class AppKernel {
@DeclareGlobalMiddleware()
globalMiddlewares = [sessionMiddleware()]
}
Queue
// ❌ Old (no longer works)
import { configureQueue, registerJob } from '@lockness/core'
// ✅ New (explicit import)
import { configureQueue, registerJob } from '@lockness/queue'
Cache System
// ❌ Old (no longer works)
import { cache, configureCache } from '@lockness/core'
// ✅ New (explicit import)
import { cache, configureCache } from '@lockness/cache'
// Note: Hono's cache middleware is still in core:
import { cache as honoCache } from '@lockness/core'
app.useMiddleware(honoCache())
FAQ
Q: Why split packages?
A: Lightweight apps don't need sessions/queues. Explicit imports show exactly
what features are used.
Q: Is @lockness/core enough for an API?
A: Yes! It includes Hono with jwt, cors, logger, and all middleware you need.
Q: What about Hono's cache/logger/validator?
A: They're HTTP middleware (still in core). Separate packages are
application-level systems.
Q: Do I need to install Hono separately?
A: No. @lockness/core re-exports everything from Hono. Never install Hono
directly.
Q: Can I use Hono middleware with Lockness?
A: Yes! All Hono middleware is available through @lockness/core.