1
0
Fork
You've already forked zerva
0
🌱 Simple event driven server
  • TypeScript 75.3%
  • JSON-with-Comments 11.2%
  • HTML 9.9%
  • JavaScript 3.4%
  • Shell 0.2%
Find a file
2026年03月30日 15:47:43 +02:00
.github remove actions 2025年03月31日 16:47:23 +02:00
.vscode feat: --clear 2025年10月06日 11:51:56 +02:00
docker fix: eslint 2024年08月14日 18:15:05 +02:00
examples update 2026年03月30日 15:47:24 +02:00
scripts fix browser exports 2026年03月12日 21:05:15 +01:00
zerva-basic-auth update 2026年03月30日 15:47:24 +02:00
zerva-bin update 2026年03月30日 15:47:24 +02:00
zerva-core update 2026年03月30日 15:47:24 +02:00
zerva-email update 2026年03月30日 15:47:24 +02:00
zerva-http update 2026年03月30日 15:47:24 +02:00
zerva-http-log update 2026年03月30日 15:47:24 +02:00
zerva-mqtt update 2026年03月30日 15:47:24 +02:00
zerva-plausible update 2026年03月30日 15:47:24 +02:00
zerva-rpc update 2026年03月30日 15:47:24 +02:00
zerva-sqlite update 2026年03月30日 15:47:24 +02:00
zerva-vite update 2026年03月30日 15:47:24 +02:00
zerva-websocket update 2026年03月30日 15:47:24 +02:00
.editorconfig Init 2021年07月08日 21:04:32 +02:00
.gitattributes Switch to mono repo 2022年09月30日 11:59:10 +02:00
.gitignore work on e2e 2025年08月30日 12:51:30 +02:00
eslint.config.js update and optimize code 2025年08月24日 12:21:35 +02:00
icon.png Switch to mono repo 2022年09月30日 11:59:10 +02:00
LICENSE fix: catch more issues for http 2024年03月05日 17:18:57 +01:00
MONOREPO.md fix: eslint 2024年08月14日 18:15:05 +02:00
package.json 0.87.0 2026年03月30日 15:47:43 +02:00
pnpm-workspace.yaml update 2026年03月30日 15:47:24 +02:00
README.md Fix linter messages 2023年05月11日 11:45:33 +02:00
SECURITY.md Add security info 2021年10月25日 10:59:42 +02:00
tsconfig.json fix: eslint 2024年08月14日 18:15:05 +02:00
tsdown.config.ts tsdown 2026年03月12日 20:57:22 +01:00
vitest.config.ts fix: eslint 2024年08月14日 18:15:05 +02:00
zerva-http-bun.zip rollback bun experiment 2025年10月13日 12:14:31 +02:00
zerva-openapi.zip archive openapi 2025年10月13日 12:35:54 +02:00
zerva-qrcode.zip feat: qrcode for http server 2025年10月15日 16:58:59 +02:00
zerva-sqlite-bun.zip rollback zerva-sqlite-bun 2025年10月13日 12:18:25 +02:00

🌱 Zerva

Minimal event driven web service infrastructure.

Get started

Set up your first project using this template.

How it works

It all starts with the context which is the common ground for any module we use or create. It serves as a hub/bus for emitting and listening on events.

Usually you would start to build a server like this:

import { useHttp } from '@zerva/http'
useHttp({
 port: 8080
})

serve itself is a module that i.e. it is a function working on context. It takes a function to call other modules and provides a common lifecycle by emitting serveInit and serveStart. These are the entry points for other services.

useHttp for example will set up an express server and start it on serveStart. It will emit httpInit before it starts and httpRunning when it is ready.

By convention, we add use to module initializer to be able to identify them at first glance.

You can write your own module which can use httpInit to add some listeners:

function useCounter() {
 let counter = 0
 on('httpInit', ({ get }) => {
 get('/counter', () => `Counter ${counter++}`)
 })
}

As you can see a module is just a function connecting itself to the context. But where is the context? Well context is set globally. Similarly, as for Vue and React our helper routines like on or emit make use of it. This is a great simplification while still being a robust approach.

If you want to use multiple contexts just wrap the code using it into withContext(context, () => { /* your code */ }).

On httpInit we make use of the http-modules specific get helper to answer to http-requests on /counter.

To make sure the http module is around as well in our context, it is good practice to register oneself and tell about dependencies using register:

function useCounter() {
 register('counter', ['http'])
 let counter = 1
 on('httpInit', ({ get }) => {
 get(
 '/',
 () => `Counter ${counter++}.<br><br>Reload page to increase counter.`
 )
 })
 return {
 getCounter: () => counter,
 }
}

As you can see we can also return some custom data or functions from our module, like getCounter in our case.

That's basically it!

Command line convenience

For convenience, you can use the zerva command line tool. It is based on estrella and translates your Typescript code on the fly without further configuration. It also watches for changes and restarts the server immediately. To build add build as first argument. The last argument can point to the entry file (Javascript or Typescript), otherwise src/main.ts will be used.

In your package.json you might want to add these lines:

{
 "scripts": {
 "start": "zerva",
 "build": "zerva build",
 "serve": "node dist/main.cjs"
 }
}

Docker

Zerva integrates perfectly with Docker. Learn more at demos/docker.

GitHub Templates

To get started, you can use these GitHub Templates:

External Modules

Advanced Topics

Conditional building

Zerva uses esbuild to create both the development server code and the production code. You can take advantage of conditional building using defines. This can be used to have code that avoids certain imports or otherwise unneed stuff in production mode. I.e. in your code you can do stuff like this:

if (ZERVA_DEVELEPMENT) {
 /* do something */
}

Valid defines are:

  • ZERVA_DEVELOPMENT is true when started as zerva
  • ZERVA_PRODUCTION is true when started as zerva build

For better compatibility the defines can also be accessed as process.env.ZERVA_DEVELOPMENT and process.env.ZERVA_PRODUCTION.

Minimal Requirements

  • Node: 16
  • JS target: es2022

See tsconfig/bases to learn details about the configuration considerations.

  • zeed - Helper lib providing the logging for server
  • zeed-dom - Lightweight offline DOM