Skip to content
Wooks

Composables for Node.js

No req/res. No middleware. Just functions.

Your handlers, simplified.

Express
ts
// Middleware chain + req/res threading
app.post('/users',
  bodyParser.json(),
  authenticate,
  async (req, res) => {
    res.status(201).json({ name: req.body.name })
  }
)
Wooks
ts
// Just call what you need
app.post('/users', async () => {
  await useAuthorization()
  const user = await useBody().parseBody<User>()
  return { name: user.name } // status 201 is default for POST
})

One pattern. Every event type.

HTTP, WebSocket, CLI, Workflows — the same composable API everywhere. Learn once, use anywhere.

Try it →
ts
import { createHttpApp, useRouteParams } from '@wooksjs/event-http'
import { useBody } from '@wooksjs/http-body'

const app = createHttpApp()

app.post('/users/:org', async () => {
  const { parseBody } = useBody()
  const { get } = useRouteParams<{ org: string }>()
  const user = await parseBody<{ name: string }>()
  return { org: get('org'), created: user.name }
})

app.listen(3000)
ts
import { createHttpApp } from '@wooksjs/event-http'
import { createWsApp, useWsMessage, useWsRooms } from '@wooksjs/event-ws'

const http = createHttpApp()
const ws = createWsApp(http)

http.upgrade('/ws', () => ws.upgrade())

ws.onMessage('message', '/chat/:room', () => {
  const { data } = useWsMessage<{ text: string }>()
  const { broadcast } = useWsRooms()
  broadcast('message', data)
})

http.listen(3000)
ts
import { createCliApp, useCliOption, useRouteParams } from '@wooksjs/event-cli'

const app = createCliApp()

app.cli('deploy :env', () => {
  const { get } = useRouteParams<{ env: string }>()
  const verbose = useCliOption('verbose')
  return `Deploying to ${get('env')}...`
})

app.run()
ts
import { createWfApp, useWfState } from '@wooksjs/event-wf'

const app = createWfApp<{ approved: boolean }>()

app.step('review', {
  input: 'approval',
  handler: () => {
    const { ctx, input } = useWfState<{ approved: boolean }>()
    ctx().approved = input<boolean>() ?? false
  },
})

app.flow('approval-process', [
  'validate', 'review',
  { condition: 'approved', steps: ['notify-success'] },
  { condition: '!approved', steps: ['notify-rejection'] },
])

Released under the MIT License.