Plugin-first enterprise backend framework built on Hono for Node.js, Deno, Bun, and Cloudflare Workers.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Plugin-first enterprise backend framework built on Hono.
Enterprise architecture without the weight. Runtime freedom without the chaos.
[!IMPORTANT] Status:
v0.11.0publishes 52 packages to npm under@setu-ts. Versions published before the move to npm remain on JSR, and nothing new is published there.The kernel, the runtime layer, 41 plugins, the three starters, the test utilities, the client SDK, and the
setuCLI are implemented, tested, and documented.Every release from
v0.2.0on is a normal release rather than a prerelease. The registry pointslatestat the current one, so a bare install resolves, where everyalphaversion had to be pinned by hand.The label changed; the stability promise did not. This is pre-1.0 software — under semver
0.xthe public API is not stable, and a minor bump carries breaking changes. See Versioning for what each bump commits us to, and CHANGELOG.md for known limitations.
Building enterprise backends today forces a difficult choice:
| Option | Problem |
|---|---|
| Hono | Extremely fast and runtime-portable, but intentionally minimal — no DI, no modules, no enterprise patterns. |
| NestJS | Rich enterprise features, but tightly coupled to Node.js, requires decorators and DI, and carries a steep learning curve. |
| Fastify | Fast and plugin-oriented, but lacks enterprise abstractions like repository patterns, CQRS, and multi-tenancy. |
| Express | Ubiquitous but aging, callback-based, and Node.js-only. |
Every existing solution forces a compromise: power vs. portability, features vs. simplicity, opinion vs. flexibility.
Setu-TS resolves this compromise. It combines:
Without becoming heavyweight. Without forcing opinions. Without locking you in.
| Principle | What It Means |
|---|---|
| Plugin-first | Every capability — logging, database, auth, validation — is a plugin. The kernel ships with zero features. |
| Runtime independent | No package except the runtime plugin uses runtime-specific APIs. Business logic never touches process.env or fs. |
| Optional DI | Dependency injection is a plugin, not a requirement. Use it if you want it; skip it if you do not. |
| Optional decorators | Decorators are a plugin, not a requirement. Every feature has a complete programmatic API. |
| Explicit APIs | No magic. No hidden globals. No reflection required. Everything is explicit and inspectable. |
| Type safety | Strict TypeScript throughout. No any in public APIs. Full type inference for services, config, and routes. |
| Tree-shakeable | Every package uses ES modules and subpath exports. You ship only what you use. |
| Production ready | Built for scale: graceful shutdown, distributed locking, circuit breakers, audit trails, and observability. |
| Enterprise focused | Patterns that large organizations need: multi-tenancy, feature flags, secrets management, CQRS, domain events. |
Status legend: ✅ Implemented — shipped, tested, and documented · 📋 Designed — specified in the roadmap, not yet built · 🚧 Planned — future design work.
Every ✅ row is a package in this repository with 90%+ test coverage on branch, function, and line.
| Feature | Status | Package | Description |
|---|---|---|---|
| Plugin system | ✅ | kernel | Capability-token-based plugin architecture |
| Middleware pipeline | ✅ | kernel | ASP.NET Core-style ordered middleware |
| Routing | ✅ | kernel | Hono LinearRouter under the framework's own pipeline |
| Runtime abstraction | ✅ | runtime | Node.js, Deno, Bun, Cloudflare Workers with detection |
| Streaming responses | ✅ | kernel + runtime | IResponse.stream() with request AbortSignal |
| Exceptions | ✅ | exceptions | Error hierarchy, RFC 9457 Problem Details, handler |
| Testing | ✅ | testing | Test app factory, mock plugins, request injection |
| Feature | Status | Package | Description |
|---|---|---|---|
| Logging | ✅ | logger-plugin | Console, pino, noop; request/response middleware |
| Configuration | ✅ | config-plugin | Env loading, variable expansion, schema validation |
| Validation | ✅ | validation-plugin | Zod-based, with RFC 9457 / NestJS / default error shapes |
| HTTP security | ✅ | http-security-plugin | CORS, security headers, CSRF, request size, IP rules |
| Authentication | ✅ | auth-plugin | JWT (HS256/RS256 via Web Crypto), API keys, local, refresh tokens, rate limiting |
| Authorization | ✅ | auth-plugin | RBAC with transitive role hierarchy and permission guards |
| GraphQL | ✅ | graphql-plugin | Schema-first and code-first, GraphQL-over-HTTP, depth limit, GraphiQL |
| Feature | Status | Package | Description |
|---|---|---|---|
| Database | ✅ | database-plugin | Memory, Prisma, Drizzle, MongoDB, DynamoDB, Cosmos DB, Bigtable — repository pattern and Unit of Work |
| Caching | ✅ | cache-plugin | Memory (LRU), Redis, noop; transparent response caching |
| Storage | ✅ | storage-plugin | S3, B2, GCS, Azure Blob, local, memory; upload middleware |
| Multi-tenancy | ✅ | multi-tenancy-plugin | Subdomain/header/path/JWT resolution; column isolation, schema/database strategies for a custom store |
| Feature | Status | Package | Description |
|---|---|---|---|
| Events | ✅ | events-plugin | In-process domain event bus |
| CQRS | ✅ | cqrs-plugin | Command and query buses with pipeline behaviors |
| Messaging | ✅ | messaging-plugin | Memory, Redis Streams, RabbitMQ, NATS, Kafka, GCP Pub/Sub, Azure Service Bus, custom; request-reply |
| Queue | ✅ | queue-plugin | Background jobs over memory, Redis, RabbitMQ, SQS; SNS fan-out; retries, cron |
| Scheduler | ✅ | scheduler-plugin | Cron, interval, delayed jobs with distributed locking |
| Worker pool | ✅ | worker-pool-plugin | CPU-bound work on real worker threads, off the event loop |
| Feature | Status | Package | Description |
|---|---|---|---|
| Service discovery | ✅ | service-discovery-plugin | Static, Consul, Kubernetes, DNS-SRV; balancing, watch, ejection |
| gRPC | ✅ | grpc-plugin | Co-serve gRPC, Connect, and gRPC-Web on the same port |
| Cloudflare | ✅ | cloudflare-plugin | Worker bindings; KV cache, R2 storage, D1, Queues, messaging, KV sessions |
| Static files | ✅ | static-plugin | ETag, Range, precompressed sidecars, SPA fallback, streaming |
| Feature | Status | Package | Description |
|---|---|---|---|
| Server-Sent Events | ✅ | sse-plugin | One-way streaming, named channels, heartbeat, Last-Event-ID |
| WebSocket | ✅ | websocket-plugin | Full-duplex on all four runtimes; rooms, heartbeat, limits |
| Cross-replica fan-out | ✅ | realtime-backplane-plugin | Rooms and channels reach clients on other replicas |
| React SSR | ✅ | react-router-plugin | React Router v8 framework mode with file-based routing |
| Server-rendered views | ✅ | view-plugin | @Render + renderView over hono-jsx / hono-html engines |
| Localization | ✅ | localization-plugin | Message catalogues, request locale resolution, a formatter shared with the browser |
| Feature | Status | Package | Description |
|---|---|---|---|
| Health checks | ✅ | health-plugin | /health, /live, /ready with pluggable indicators |
| Metrics | ✅ | metrics-plugin | Prometheus counters, gauges, histograms, summaries |
| Telemetry | ✅ | telemetry-plugin | OpenTelemetry tracing, W3C propagation, auto-instrumentation |
| OpenAPI | ✅ | openapi-plugin | OpenAPI 3.1 from routes, Zod transform, Swagger UI |
| Audit logging | ✅ | audit-plugin | Immutable trail over memory, log, database, or file |
| Resilience | ✅ | resilience-plugin | Circuit breaker, retry, timeout, bulkhead |
| Idempotency | ✅ | idempotency-plugin | Answers a repeat of completed work from its record or skips it (memory, Redis, Durable Objects) |
| Secrets | ✅ | secrets-plugin | Env, AWS KMS, GCP Secret Manager, Azure Key Vault, Vault |
| Feature | Status | Package | Description |
|---|---|---|---|
| ✅ | mail-plugin | Log, SMTP, SES, SendGrid with a template engine | |
| Notifications | ✅ | notification-plugin | Email, SMS, push, Slack over one HTTP seam |
| Feature flags | ✅ | feature-flags-plugin | Percentage rollout, user targeting, pluggable providers |
| Dependency injection | ✅ | di-plugin | Optional. Singleton/scoped/transient, constructor injection |
| Decorators | ✅ | decorator-plugin | Optional. NestJS-style, no reflect-metadata |
| Feature | Status | Package | Description |
|---|---|---|---|
| CLI | ✅ | cli | setu — project scaffolding and plugin-aware code generation |
| Client SDK | ✅ | sdk | HTTP client with retry, circuit breaker, OpenAPI codegen |
| Test utilities | ✅ | testing | createTestApp, mock plugins/registry, fixtures, stream reads |
| Starter bundles | ✅ | rest-starter, microservice-starter, full-stack-starter | createRestApp, createMicroserviceApp, createFullStackApp — pre-wired plugin sets with per-plugin option arms |
# Node (pnpm add / yarn add work the same way)
npm install @setu-ts/kernel@^0.11.0 @setu-ts/runtime@^0.11.0
# Bun
bun add @setu-ts/kernel@^0.11.0 @setu-ts/runtime@^0.11.0
# Deno
deno add npm:@setu-ts/kernel@^0.11.0 npm:@setu-ts/runtime@^0.11.0
The @^0.11.0 is recommended, not required. npm points latest at the current release, so a
bare npm install @setu-ts/kernel resolves without a version. Pin anyway if you would rather meet
the next breaking release as a deliberate upgrade than as a surprise — see
Versioning. Earlier releases are on JSR only; see the
upgrading guide to move an existing project to npm.
Every release up to v0.1.0-alpha.10 was a prerelease, which JSR never tags as latest, so a bare
install failed outright on those.
If you install within 24 hours of a release, Deno's supply-chain policy also refuses versions
younger than a day. Pass --min-dep-age 0 to override it, or wait it out.
npx @setu-ts/cli new my-app --template rest # or: npm create @setu-ts my-app -- --template rest
cd my-app && npm install && npm start
setu is a Node program on npm; npm install --global @setu-ts/cli puts it on your PATH. Node is
the default target — --runtime deno, bun or cloudflare-workers scaffolds the others, each
installing the framework from npm with its own package manager.
All 52 workspace members ship as one release train: the core (common, kernel, runtime,
exceptions, testing), every plugin in the tables above, the three starters, the sdk, the cli
and create — on npm from v0.9.0, which publishes localization-plugin, idempotency-plugin and
create for the first time. Earlier releases were published on JSR.
Every plugin is a separate package — add only what you use. Heavy dependencies (Prisma, ioredis, nodemailer, the OpenTelemetry SDK, …) are never hard dependencies: each is injected through plugin options or imported lazily, so an application pays only for the capabilities it configures.
Setu-TS is pre-1.0, and the version number says exactly what that means:
| Bump | What it carries |
|---|---|
Minor — 0.5 → 0.6 | Breaking changes. Every one is listed in CHANGELOG.md with migration text. |
| Patch — the third number | Fixes and additions only. Safe to take without reading anything. |
Under semver a ^0.11.0 range means >=0.11.0 <0.12.0, so a caret pin absorbs patches and stops at
the next breaking release. That is the intended way to depend on this project today.
From 0.9.0 the patch is the normal release and breaking changes are batched into an occasional
minor: a change that would break a caller or an implementor ships behind its old behaviour first (a
flag, an optional member, a deprecation) and the removal waits for the next minor. Two gates hold
the line — a milestone plan must state what it breaks and which minor carries it, and
release:verify refuses a patch whose changelog carries a BREAKING entry.
Releases up to v0.1.0-alpha.10 used a prerelease suffix instead. Dropping it is a change of label,
not of policy — 0.x already grants exactly the same licence to break, and it drops the JSR
prerelease penalty that forced every install line to be pinned by hand.
1.0 is the API freeze, and it is gated on Milestone 40: benchmarks, a security audit, and the Node/Bun compatibility suites as release gates. Until then, read the CHANGELOG before a minor bump.
A small application — the kernel, a runtime, and a logger. Add the logger to the two packages
installed above (npm install @setu-ts/logger-plugin@^0.11.0), save this as main.ts:
import { createApplication } from '@setu-ts/kernel';
import { RuntimePlugin } from '@setu-ts/runtime';
import { LoggerPlugin } from '@setu-ts/logger-plugin';
const app = createApplication({
plugins: [RuntimePlugin(), LoggerPlugin({ level: 'info' })],
});
app.router.get('/', (ctx) => {
return ctx.response.json({ message: 'Hello, World!' });
});
await app.start({ port: 3000 });
and run it with deno run --allow-net --allow-env main.ts (--allow-env because the runtime plugin
reads the process environment).
No decorators. No DI. No modules. Just a router, a runtime, and a logger.
Add capabilities as you need them:
import { createRuntimeServices } from '@setu-ts/runtime';
import { ConfigPlugin, loadConfig } from '@setu-ts/config-plugin';
import { ValidationPlugin } from '@setu-ts/validation-plugin';
import { DatabasePlugin } from '@setu-ts/database-plugin';
import { AuthPlugin } from '@setu-ts/auth-plugin';
import { OpenApiPlugin } from '@setu-ts/openapi-plugin';
// Plugin options are built before any plugin registers, so a value a plugin
// needs at construction comes from configuration loaded first. The same
// snapshot is then registered, so handlers read exactly these values.
const config = await loadConfig(createRuntimeServices(), { validationSchema: AppConfigSchema });
app.register(ConfigPlugin({ instance: config }));
app.register(ValidationPlugin());
// A Prisma v7 client is generated into an application-owned output path and
// needs a driver adapter, so the application constructs it and injects it.
app.register(DatabasePlugin({ type: 'prisma', options: { prismaClient } }));
// Secrets come from configuration, never process.env (runtime independence).
app.register(AuthPlugin({ jwt: { secret: config.getOrThrow<string>('JWT_SECRET') } }));
app.register(OpenApiPlugin({ title: 'My API', version: '1.0.0' }));
Traditional frameworks grow forever. Every feature is baked into the core, and the core becomes a monolith.
graph LR
subgraph Traditional Framework
TC[Core] --> TF1[Auth]
TC --> TF2[Database]
TC --> TF3[Validation]
TC --> TF4[Logging]
TC --> TF5[...everything]
TC --> TF6[Forever growing]
end
Plugin-first frameworks stay small. The kernel only orchestrates plugins. Capabilities are composable and replaceable.
graph TB
subgraph Plugin-First Framework
K[Small Kernel] --> PR[Plugin Registry]
PR --> P1[Logger Plugin]
PR --> P2[Database Plugin]
PR --> P3[Auth Plugin]
PR --> P4[Validation Plugin]
PR --> P5[Your Custom Plugin]
PR --> P6[Any Plugin]
end
| Traditional | Plugin-First |
|---|---|
| Core grows with every feature | Kernel stays small and stable |
| All features are bundled | Include only what you use |
| Swapping a feature requires forking | Replace any plugin via capability tokens |
| Heavy startup cost | Lazy initialization, pay for what you use |
| Hard to test in isolation | Each plugin is independently testable |
A pnpm workspace. Every package is published independently to npm; releases before v0.9.0 were
published to JSR.
setu-ts/
├── packages/ # 52 workspace members, published on npm (JSR before v0.9.0)
│ ├── common/ # Shared contracts, capability tokens (no dependencies)
│ ├── kernel/ # Plugin kernel, middleware pipeline, router
│ ├── runtime/ # Runtime services and HTTP adapters (Node, Deno, Bun, Workers)
│ ├── exceptions/ # Exception factories and error-handler middleware
│ ├── testing/ # Test utilities
│ ├── *-plugin/ # 41 capability plugins
│ ├── cli/ # CLI tool — `setu`, project scaffolding and code generation
│ ├── sdk/ # Client SDK — HTTP client, interceptors, resilience, OpenAPI codegen
│ └── starters/ # Plugin bundles — REST, microservice, full-stack starters (M36)
├── scripts/ # Coverage, plan linting, npm release tooling
├── docs/ # Operator guides (releasing, telemetry fan-out, …)
├── docker/ # Docker and OpenTelemetry Collector configurations
├── k8s/ # Helm chart and the manifests it renders (M39)
├── plans/ # One plan per milestone, archived on completion
├── apps/ # Example applications — 15 runnable apps (M37, M37b, M37c, M55)
├── ARCHITECTURE.md # Technical architecture guide
├── PUBLIC_API.md # Public API contract
├── AI_GUIDELINES.md # Engineering guidelines
├── ROADMAP.md # Implementation roadmap, milestones 0–75
├── CHANGELOG.md # Release notes
└── README.md # This file
Dependency rule: no plugin imports another plugin. Plugins communicate only through capability
tokens resolved from the service registry (ctx.services.get<T>(CAPABILITIES.X)), so any plugin can
be replaced without touching the others.
| Document | Audience | Purpose |
|---|---|---|
| docs/README.md | All users | Documentation hub — navigation and guide index |
| ARCHITECTURE.md | Framework contributors | How the framework works internally and why it was designed this way |
| PUBLIC_API.md | Application developers | How to use the framework — complete examples for every plugin |
| AI_GUIDELINES.md | All contributors | Permanent engineering rules — TypeScript, testing, security, performance |
| ROADMAP.md | Implementation tracking | Milestone-by-milestone implementation roadmap with package details |
| CHANGELOG.md | Everyone | What each release contains, and its known limitations |
| docs/releasing.md | Maintainers | npm release runbook — setup, trust, and the per-release sequence |
Each package also carries its own README with options, semantics, and a worked example.
Start here:
We welcome beta feedback, reproducible bug reports, documentation corrections, focused fixes, and plugins built on the capability model. Start with CONTRIBUTING.md for the channel to use, the maintainer-triaged pull-request flow, and the engineering requirements for accepted implementation work.
Please report security concerns privately through SECURITY.md, and follow the Code of Conduct in every project space.
The goal is straightforward:
Become the most practical enterprise backend framework for TypeScript.
Practical means:
deno compile.This is a framework designed to be adopted incrementally, extended safely, and trusted in production.
MIT © Setu-TS Contributors
Documentation Hub · Architecture · Public API · Guidelines · Roadmap