@setu-ts/microservice-starter
Opinionated plugin composition for building microservices with Setu-TS.
Extends the REST starter bundle with additional capabilities essential for distributed systems: messaging, queue processing, resilience patterns, and telemetry. Ideal for service-oriented architectures requiring async communication, circuit breakers, and observability.
Installation
npm install @setu-ts/microservice-starter
# Deno: deno add npm:@setu-ts/microservice-starter
Or via npm/yarn/pnpm:
npm install @setu-ts/microservice-starter
Usage
The starter exports createMicroserviceApp — a fully wired application combining REST plugins plus
microservice-specific features:
import { createMicroserviceApp } from '@setu-ts/microservice-starter';
const app = createMicroserviceApp();
app.router.get('/hello', (ctx) => ctx.response.text('Hello world'));
await app.start({ port: 3000 });
With Options
Customize all plugin configurations through the optional options parameter:
import { createMicroserviceApp } from '@setu-ts/microservice-starter';
import type { MicroserviceStarterOptions } from '@setu-ts/microservice-starter';
const options: MicroserviceStarterOptions = {
// REST base plugins (see rest-starter)
config: {/* ... */},
logger: {/* ... */},
// Microservice additions
messaging: {/* messaging plugin options */},
queue: {/* queue plugin options */},
resilience: {/* resilience plugin options */},
telemetry: {/* telemetry plugin options */},
};
const app = createMicroserviceApp(options);
Advanced Plugin Composition
Use buildMicroservicePlugins together with createApplication from the kernel to construct a
custom plugin array with full control over ordering and configuration:
import { buildMicroservicePlugins } from '@setu-ts/microservice-starter';
import { createApplication } from '@setu-ts/kernel';
const app = createApplication({
plugins: buildMicroservicePlugins({
messaging: {}, // provide options object; omit to use default
queue: {/* custom config */},
// telemetry omitted to exclude (no-op default)
}),
});
Options
MicroserviceStarterOptions extends RestStarterOptions, so every REST option above applies
here unchanged. Four fields are added, one per plugin this tier registers on top:
| Option | Type | Omitted → |
|---|---|---|
messaging | MessagingPluginOptions | in-memory broker default |
queue | QueuePluginOptions | memory adapter default |
resilience | ResiliencePluginOptions | plugin defaults |
telemetry | TelemetryPluginOptions | no-op — no exporter configured |
Unlike the REST tier’s gated arms, these four plugins are always registered; the options only
configure them. That is what makes createMicroserviceApp() with no arguments a working service
rather than an inert one.
Included Plugins
| Category | Plugin | Description |
|---|---|---|
| REST Base | RuntimePlugin | Core runtime integration |
| ConfigPlugin | Configuration management | |
| LoggerPlugin | Structured logging | |
| ValidationPlugin | Request validation | |
| HttpSecurityPlugin | Security headers | |
| HealthPlugin | Health check endpoints | |
| MetricsPlugin | Metrics collection | |
| OpenApiPlugin | OpenAPI documentation | |
| DecoratorPlugin | Decorator-based routing | |
| DatabasePlugin | Optional database access | |
| AuthPlugin | Optional authentication | |
| Microservice | MessagingPlugin | Async message bus support |
| QueuePlugin | Background job queueing | |
| ResiliencePlugin | Circuit breaker & retries | |
| TelemetryPlugin | Tracing & observability |
OpenApiPlugin self-hosts Swagger UI by default, so install swagger-ui-dist (^5) in the consuming
application, or pass openapi: { swagger: { assets: 'cdn' } }. Without either, startup fails with
OptionalDependencyUnavailableError.
The inherited auth arm accepts any AuthPluginOptions with at least one passive strategy (jwt,
apiKey, session, or strategies). When present, AuthPlugin installs authentication middleware
globally at priority 300 unless auth.middleware disables or moves it.
All microservice plugins are enabled by default; individual plugins can be configured or omitted via options.
Workers Portability
This starter bundles MessagingPlugin and QueuePlugin, which require raw network sockets
(TCP/UDP) and are therefore not compatible with Cloudflare Workers. This starter is for Node.js,
Deno, or Bun runtimes only — matching the CLI’s refusal of
--template microservice --runtime cloudflare-workers. The REST base plugins (Runtime, Config,
Logger, etc.) are all edge-safe.
Multi-instance Restriction + Escape Hatch
The four multi-instance plugins (cache, database, queue, messaging) accept an
options.name parameter that creates a derived capability token. The starter registers one
instance per arm on the bare token (e.g., CAPABILITIES.CACHE, CAPABILITIES.MESSAGING). Setting
name through a starter arm moves the plugin off the bare token, which will break any code that
resolves the capability (including health checks and documentation examples).
The starter does not support setting name through its option arms. If you need a second
instance (e.g., a session cache distinct from the default, or a separate queue for dead-letter
processing), register it manually after the starter returns:
import { createMicroserviceApp } from '@setu-ts/microservice-starter';
import { CachePlugin } from '@setu-ts/cache-plugin';
import { QueuePlugin } from '@setu-ts/queue-plugin';
const app = createMicroserviceApp();
app.register(CachePlugin({ name: 'session' }));
app.register(QueuePlugin({ name: 'dead-letter' }));
This escape hatch works because createMicroserviceApp returns an un-started IKernelApplication
that accepts additional registrations.
Realtime and DI arms
createMicroserviceApp inherits the realtime and di arms from the REST starter — the option
type extends RestStarterOptions, so every sub-arm behaves identically and nothing new is
registered by default.
const app = createMicroserviceApp({
di: {},
realtime: { sse: {}, websocket: {}, backplane: { transport: 'messaging' } },
});
{ transport: 'messaging' } works on this tier without extra wiring: MessagingPlugin is always
registered, so the backplane finds a broker under CAPABILITIES.MESSAGING. On the REST tier that
combination throws at start().
See rest-starter for the full description of each arm.
Coming from NestJS
| NestJS | Setu-TS |
|---|---|
@Module({ … }) | A plugin — IPlugin with provides: [CAPABILITIES.X] |
providers: [UserService] | decorators: { services: [UserService] }, or app.register(…) |
@Injectable() | @Injectable({ token, scope }) |
| Constructor injection by type | @Inject(token, …) on the class, one entry per argument |
@Controller('/users') | @Controller('/users') — identical |
@Get() / @Post() | @Get() / @Post() — identical |
@Body() / @Query() | @Params(Body(), Query()) — sources, listed in argument order |
Guard (CanActivate) | @UseGuards(fn), or an auth-plugin guard factory |
Pipe (ValidationPipe) | @ValidateBody(schema) (Zod) |
| Interceptor | @UseInterceptors(fn) |
| Exception filter | @UseFilters(fn), or errorHandler() middleware |
imports: [OtherModule] | ctx.services.get(CAPABILITIES.X) — no plugin imports another |
| DI is required | DI is the optional di arm |
The one difference that will bite you: constructor injection needs an explicit token.
import { Inject, Injectable } from '@setu-ts/decorator-plugin';
import { CAPABILITIES, type ILogger } from '@setu-ts/common';
@Injectable({ token: 'user-service' })
@Inject(CAPABILITIES.LOGGER)
class UserService {
constructor(private logger: ILogger) {}
}
constructor(private db: DatabaseService) cannot work here. Inferring the token from the
parameter’s type requires emitDecoratorMetadata, which Deno does not support — so the type is
simply not available at runtime. This is permanent, not a gap waiting to be filled.
Two consequences follow from the list being positional:
- The Nth entry binds the Nth constructor argument, so reordering the constructor without reordering the tokens misinjects every argument — they are one declaration and move together.
- A list shorter than the constructor leaves the trailing arguments
undefined; a positional list cannot have gaps. Method parameters are separate, and bind with@Params(...).
See Also
Exports
| Export | Kind |
|---|---|
buildMicroservicePlugins | function |
createMicroserviceApp | function |
MicroserviceStarterOptions | interface |
RealtimeArm | interface |
Generated from the package barrel by pnpm run docs:exports; pnpm run check:docs fails when it
drifts.