@xenosisorg/xenosis-core
v0.0.12
Published
Microservice toolkit for Node.js / TypeScript
Maintainers
Readme
Xenosis
Opinionated TypeScript microservice toolkit. awilix DI without decorators, shared schema packages for databases, type-safe inter-service RPC from a JSON config — purpose-built for TypeScript microservice monorepos.
Status: v0.1 — working end-to-end.
🌐 xenosis.org — full docs, examples, roadmap
Install
# CLI — workspace scaffolding (services, schemas, peer APIs, MCP setup)
npm i -g @xenosisorg/xenosis-cli
# Per-package, added automatically by `xenosis create app`:
npm i @xenosisorg/xenosis-core # runtime: bootstrap, DI, peers, sockets
npm i -D @xenosisorg/xenosis-testing # in-process service boot + supertest + peer mocks
npm i -g @xenosisorg/xenosis-mcp # MCP server for Claude / Cursor / Claude Desktop| Package | What it is |
|---|---|
| @xenosisorg/xenosis-cli | xenosis create app/service/api/schema, xenosis dev, xenosis graph, xenosis sync api |
| @xenosisorg/xenosis-core | Runtime: xenosisBootstrap, Handler, Router, definePeerApi, defineSocketApi, autoload |
| @xenosisorg/xenosis-testing | In-process service boot, in-memory Postgres (PGlite), peer mocks, supertest factory |
| @xenosisorg/xenosis-mcp | MCP server exposing workspace-aware tools to AI agents (graph, traces, replay) |
Why Xenosis
Xenosis is built specifically for TypeScript microservice projects. It gives you everything a service needs to boot and talk to its neighbors, without the boilerplate every service usually re-implements.
What Xenosis covers out of the box:
- Service bootstrap (HTTP server, config loading, lifecycle, signals)
- Dependency injection through awilix — no decorators, no
reflect-metadata, no module system - Multi-database orchestration via shared schema packages (one schema, many services)
- Type-safe inter-service RPC defined in a shared npm package
- External / third-party API integration with the same contract shape
- Retry, timeout, and circuit-breaker for every peer call
- A scaffolding CLI that generates services, APIs, and schemas from a single workspace config
Designed for microservice projects of every size — from a 3-service prototype to a 30-service production platform. Same conventions, same scaffolding, same configuration shape.
What Xenosis actually does
- DI without decorators. awilix container, classes with destructured constructor injection. No
@Injectable(), noreflect-metadata, noexperimentalDecorators. - Multi-database via shared schema packages. A schema package (
@example/psql-main) owns aschema.prismaand exports acreateClient(connector)factory. Several services import the same package and share types + tables. See SCHEMAS.md. - Autoload by naming convention. Repositories, services, and controllers are picked up by glob (e.g.
User.repository.ts→userRepositoryin the cradle). No manualcontainer.register({...})boilerplate. Per-file__xenosisoverride escape hatch. See AUTOLOAD.md. - Type-safe inter-service RPC. Each service has a tiny API package (e.g.
apis/billing-api) that exports its types and adefineServiceApiroutes table. Sibling services call those routes withthis.api.billing.createCharge(...)— full TS inference, no codegen runtime. The routes block is regenerated byxenosis sync api <service>from/** @peer methodName */JSDoc directives on the controllers, so the contract stays in sync with what's actually exposed. HTTP transport, retry + timeout + circuit breaker via cockatiel. - External APIs via
xenosis-custom/. Third-party APIs (Stripe, Twilio, GitHub, …) keep the olderdefinePeerApi+mountPeerApishape because vendor wrappers needbodyEncoding: 'form-urlencoded',errorMapper, and custom headers per route. Internal Xenosis services usedefineServiceApi; external vendors usedefinePeerApi.
Hello world
// src/service.ts — entire bootstrap
import { xenosisBootstrap } from '@xenosisorg/xenosis-core';
import container from './container';
await xenosisBootstrap({
container,
autoload: {
repositories: { pattern: 'src/repository/*.repository.ts', lifetime: 'singleton' },
services: { pattern: 'src/services/*.service.ts', lifetime: 'singleton' },
controllers: { pattern: 'src/api/**/*.controller.ts', style: 'build' },
},
});
await container.cradle.commands.start();// xenosis.config.json
{
"name": "users-service",
"port": 4001,
"connectors": {
"psqlMain": { "type": "postgres", "url": "postgresql://localhost/main" },
"redis": { "type": "redis", "host": "localhost", "port": 6379 }
},
"schemas": {
"mainDb": { "package": "@example/psql-main", "connector": "psqlMain" }
},
"peers": {
"billing": {
"package": "@example/billing-api",
"transport": "http",
"baseUrl": "http://localhost:4002",
"retry": { "attempts": 2, "backoffMs": 200 }
},
"stripe": {
"package": "@example/xenosis-custom-stripe-api",
"transport": "http",
"baseUrl": "https://api.stripe.com",
"headers": { "Authorization": "Bearer sk_test_..." }
}
}
}// src/services/User.service.ts — autoloaded as cradle.userService
import type { ILogger } from '@xenosisorg/xenosis-core';
import type { PrismaClient } from '@example/psql-main';
import type { BillingServiceApi } from '@example/billing-api';
import type UserRepository from '../repository/User.repository';
export default class UserService {
private logger: ILogger;
private userRepository: UserRepository;
private mainDb: PrismaClient; // from schemas.mainDb
private api: { billing: BillingServiceApi }; // from peers.billing
constructor({ logger, userRepository, mainDb, api }: {
logger: ILogger;
userRepository: UserRepository;
mainDb: PrismaClient;
api: { billing: BillingServiceApi };
}) {
this.logger = logger;
this.userRepository = userRepository;
this.mainDb = mainDb;
this.api = api;
}
async upgrade(userId: string, amount: number) {
const user = await this.userRepository.findById(userId);
if (!user) throw new Error('not found');
// Type-safe peer call: `this.api.billing` is the proxy built by core
// from `config.peers.billing.package = "@example/billing-api"`.
const charge = await this.api.billing.createCharge({
userId: user.id,
amount,
currency: 'USD',
});
return { user, charge };
}
}// src/api/user/user.controller.ts — autoloaded via container.build()
import { Handler, Request, Response, Router } from '@xenosisorg/xenosis-core';
import type { IServer } from '@xenosisorg/xenosis-core';
import type UserService from '../../services/User.service';
import { upgradeBodySchema, idParamSchema } from './user.schema';
export default function UserController({
server, userService,
}: { server: IServer; userService: UserService }) {
const router = Router();
router.route('/:id/upgrade').post(
Handler(
Request.Params(idParamSchema),
Request.Body(upgradeBodySchema),
async ({ id }, body) => {
const result = await userService.upgrade(id, body.amount);
return Response.OK(result);
},
),
);
server.use('/api/v1/users', router);
}That is the entire bootstrap surface — no decorators, no modules, no nest g. A new Order.service.ts file in src/services/ is automatically registered as cradle.orderService on the next restart.
Status snapshot (what's actually shipped)
Core runtime (@xenosisorg/xenosis-core)
| Component | Status | Notes |
|---|---|---|
| xenosisBootstrap (awilix container, lifecycle, signals) | ✅ Done | lazy provider registration, graceful SIGTERM/SIGINT drain |
| Connectors (psql, mysql, mongo, dynamo, redis) | ✅ Done | single-schema fallback providers |
| Multi-schema (schemas config block, dynamic package import) | ✅ Done | one schema package shared by many services |
| Autoload (glob + naming convention + __xenosis override) | ✅ Done | arbitrary categories (jobs, workers, gateways…) |
| REST layer (Handler, Response, Exception, Request with zod) | ✅ Done | selector + handler pattern |
| Boundaries (boundaries.allowedCallers + x-xenosis-caller header) | ✅ Done | inbound peer allowlist, xenosis graph lints it |
| Authentication gate (shared token middleware, configurable exempt paths) | ✅ Done | opt-in via authentication.enabled + authentication.token |
| Tracing & request logging (x-xenosis-trace-id, child loggers, AsyncLocalStorage) | ✅ Done | middleware wired; peer calls auto-propagate child spans; requestLog config option |
| Pino structured logger (JSON in prod, pretty in dev, child loggers per request) | ✅ Done | replaces Winston |
| Production bundle (xenosis generate manifest) | ✅ Done | static-import map so autoload survives tsup / esbuild |
| OpenAPI / Swagger (auto-generated from controller selectors) | ✅ Done | /openapi.json + /docs UI, on by default |
Inter-service communication
| Component | Status | Notes |
|---|---|---|
| Internal RPC — defineServiceApi, type-safe Proxy client | ✅ Done | one API package per service, xenosis sync api <svc> regenerates from @peer JSDoc |
| External APIs (xenosis-custom/) — definePeerApi + mountPeerApi | ✅ Done | Stripe-style form-urlencoded, errorMapper, custom headers |
| Reliability (retry / timeout / circuit-breaker via cockatiel) | ✅ Done | per-binding policy in peers.<name> config |
| Inter-service auth (x-xenosis-peer-key header + boundaries.allowedCallers) | ✅ Done | rotatable shared key, declarative caller allowlist per provider |
| WebSockets (defineSocketApi, autoloaded handlers, pluggable transports) | ✅ Done | ws built-in; socket.io / uWS swap in via npm; socketBus for broadcasts; JWT-on-upgrade |
| RabbitMQ / Kafka / Redpanda / Redis Streams | ⏳ V0.4 | async transports for events / streaming |
AI-native developer experience
| Component | Status | Notes |
|---|---|---|
| Dev dashboard (xenosis dev live UI) | ✅ Done | heat-mapped peer graph, Jaeger-lite trace waterfall, request stream |
| Time-Travel Replay | ✅ Done | replay any recorded call; req.isReplay guard for side-effects; promote-to-test |
| CI graph diff (xenosis graph snapshot + xenosis graph diff) | ✅ Done | freezes peer routes + zod hashes; exits non-zero on breaking change; --gha formatter |
| MCP server (@xenosisorg/xenosis-mcp) — explain_trace, simulate_change, workspace tools | ✅ Done | exposes Xenosis runtime signals to Claude / Cursor / Claude Desktop |
Tooling
| Component | Status | Notes |
|---|---|---|
| @xenosisorg/xenosis-cli (create-xenosis-app, xenosis create service/api/schema/shared-module, xenosis dev, xenosis sync api, xenosis graph, xenosis init mcp) | ✅ Done | scaffolding + parallel dev runner + workspace lint |
| Multi-ORM schema templates | ✅ Done | Prisma (postgres / mysql), Drizzle, Knex, Mongo, Dynamo |
| TypeScript + JavaScript variants (--lang ts|js) | ✅ Done | JS variants use JSDoc; peer APIs always TS |
| Testing kit (@xenosisorg/xenosis-testing) | ✅ Done | in-process service boot, in-memory Postgres (PGlite), peer mocks, supertest factory |
| Shared modules (xenosis create shared-module) | ✅ Done | cradle singletons available across every service in the workspace |
| Docs site (xenosis.org) | ✅ Done | Astro + Tailwind, dark/light theme, interactive workspace explorer |
Roadmap (v0.4+)
| Component | Status | Notes |
|---|---|---|
| Streaming transports (Kafka / Redpanda / Redis Streams) | ⏳ V0.4 | high-throughput event streaming |
| Service discovery (Consul / k8s / DNS), deploy templates | ⏳ V1.0 | adapters + xenosis deploy <provider> |
| OTel adapter, Prometheus metrics package | ⏳ V0.2 polish | builds on the trace middleware shipped in v0.1 |
See V1_IMPLEMENTATION.md for the full breakdown and PLAN.md for phase-based planning.
Repository layout
xenosis/
├── src/ ← @xenosisorg/xenosis-core
│ ├── xenosisBootstrap.ts ← bootstrap (DI + schemas + peers + autoload)
│ ├── types.ts ← public types (SchemaPackage, AutoloadOptions, PeerApi, …)
│ ├── providers/ ← single-schema fallback providers
│ ├── libs/
│ │ ├── schemas.loader.ts ← multi-schema loader
│ │ └── autoload.loader.ts ← glob-based discovery
│ ├── peers/ ← inter-service RPC
│ │ ├── definePeerApi.ts
│ │ ├── createPeerClient.ts ← Proxy factory + zod + errorMapper
│ │ ├── mountPeerApi.ts ← provider-side mounter
│ │ ├── httpTransport.ts ← fetch + json + form-urlencoded
│ │ ├── reliability.ts ← cockatiel wrapper
│ │ ├── tracing.ts ← x-xenosis-trace-id helpers
│ │ └── loader.ts ← peers config → cradle
│ └── rest/ ← Handler / Response / Exception / Request
│
├── examples/
│ ├── apis/
│ │ ├── billing-api/ ← internal peer (Xenosis service on the other end)
│ │ └── xenosis-custom/ ← user territory: external API wrappers
│ │ └── httpbin-api/ ← form encoding + Bearer header + errorMapper
│ ├── db-schemas/
│ │ └── psql-main/ ← Prisma schema (User, Order)
│ └── services/
│ ├── users-service/ ← port 4001, canonical layout + internal peer
│ ├── billing-service/ ← port 4002, peer provider (mountPeerApi)
│ └── playground-service/ ← port 4010, external peer demo (httpbin.org)
│
├── README.md ← this file
├── PLAN.md ← phase-based roadmap (Phase 0–4)
├── V1_IMPLEMENTATION.md ← detailed plan for 0.1.0
├── SCHEMAS.md ← schema package convention
├── AUTOLOAD.md ← glob discovery convention + __xenosis override
└── pnpm-workspace.yamlSee examples/README.md for a walkthrough of every example service and how they share databases / call each other.
Roadmap
Detailed in PLAN.md. Short version:
| Phase | Focus | Status | |---|---|---| | v0.1 | Core + Multi-schema + Autoload + Peers RPC + CLI + Multi-ORM templates + Graceful shutdown + Production bundle + Docs site | ✅ Shipped | | v0.2 | Pub/sub events (RabbitMQ transport), inter-service auth, OTel adapter | 🚧 In progress | | v0.3 | Streaming transports (Kafka, Redpanda, Redis Streams) + WebSockets | ⏳ | | v1.0 | Service discovery (Consul/k8s), testing kit, deploy templates | ⏳ |
License
MIT — © 2026 Andrija Vujović.
