@skweb/framework
v9.0.0
Published
Web/cron framework integrating database, redis, httpServer for skweb.
Readme
@skweb/framework
Base framework for skweb applications. Provides WebFramework, RealtimeFramework, and CronFramework singletons with unified lifecycle management, health checks, and graceful shutdown.
Installation
npm install @skweb/frameworkWebFramework (HTTP)
import { WebFramework } from '@skweb/framework'
import { createExpressApp } from '@skweb/express'
const framework = new WebFramework({ runtimeFactory: createExpressApp })
framework.createApp()
await framework.setup({ modelsDir: './models', controllersDir: './controllers' })
framework.mountHealth() // /healthz, /readyz, /startupz
framework.start(3000)RealtimeFramework (WebSocket / Socket.IO)
Realtime server with declarative message handlers, ajv validation, middleware chain, and multi-node broadcast via Redis pub/sub.
import { RealtimeFramework, createRateLimitMiddleware } from '@skweb/framework'
import { createWsApp } from '@skweb/ws'
const rt = new RealtimeFramework({
runtimeFactory: createWsApp,
port: 3001,
redis: redisInstance, // optional: enables cross-node broadcast
onConnect: (socket) => { // optional: authentication hook
const token = socket.handshake?.headers?.authorization
if (!token) return false // reject connection
socket.data.set('userId', verifyJwt(token))
}
})
rt.createApp()
await rt.setup({ handlersDir: './messages' })
rt.mountHealth() // health probes on port 3002
await rt.loadMessageHandlers()
rt.start()Message Handlers
// messages/ping.ts
export default {
type: 'ping',
schema: { type: 'object', properties: { msg: { type: 'string' } } },
middlewares: [createRateLimitMiddleware({ max: 20, windowMs: 10_000 })],
async handle(ctx) {
ctx.socket.send('pong', { echo: ctx.payload, timestamp: Date.now() })
}
}Key Features
- Two modes: standalone (own port) or attached (share WebFramework's HTTP server)
- Authentication:
onConnecthook withsocket.handshake(headers, query) - Rate limiting:
createRateLimitMiddleware({ windowMs, max }) - Health checks:
mountHealth()->/healthz,/readyz,/startupz - Multi-node broadcast:
RedisBroadcaster(re-exported from@skweb/realtime) via@skweb/redispub/sub - Targeted delivery:
sendToSocket(socketId, type, data)/sendToUser(userId, type, data)(requires redis + onConnect to set userId) - Broadcast helpers:
broadcast(type, data)/broadcastRoom(room, type, data)convenience methods - Presence:
isUserOnline(userId)checks Redis user-socket mapping - Connection observability:
rt.connectedCountgetter
Adapters
@skweb/ws- Native WebSocket (JSON envelope{ type, data?, ackId? })@skweb/socketio- Socket.IO (native events + ack bridging)
Cross-Service Realtime via NATS
RealtimeFramework can be exposed as a Moleculer service so that web-api (or any other process) can push messages to online users via NATS RPC, without holding a WebSocket connection itself.
// realtime-worker/broker.ts
import { createMicroserviceBroker, createRealtimeService } from '@skweb/microservice'
import { framework } from './framework.js'
const broker = createMicroserviceBroker({
nodeID: 'realtime-1',
transporter: { type: 'NATS', options: { url: process.env.NATS_URL } }
})
broker.createService(createRealtimeService(framework))
await broker.start()// web-api/utils/realtime-client.ts
import { createMicroserviceClient, RealtimeClient } from '@skweb/microservice'
const sc = createMicroserviceClient({
nodeID: 'web-api',
transporter: { type: 'NATS', options: { url: process.env.NATS_URL } }
})
const rt = new RealtimeClient(sc)
await sc.start()
// In a controller:
await rt.sendToUser('user-42', 'notification', { message: 'order shipped' })
const online = await rt.isUserOnline('user-42')Available RPC actions exposed by createRealtimeService():
| Action | Params | Returns |
|--------|--------|---------|
| realtime.sendToUser | { userId, type, data? } | void |
| realtime.sendToSocket | { socketId, type, data? } | void |
| realtime.isUserOnline | { userId } | boolean |
| realtime.broadcast | { type, data? } | void |
| realtime.broadcastRoom | { room, type, data? } | void |
| realtime.getConnectedCount | — | number |
License
MIT
