Features

Pre-built feature modules for rapid application development

Features in JustScale are self-contained modules that bundle services, controllers, and configuration into reusable packages. They provide production-ready functionality that you can add to your application with a single import.

What are Features?

A feature is a composable unit that encapsulates related functionality. Features can depend on other features, and JustScale automatically resolves and initializes them in the correct order.

src/app.tsTypeScript
import { createClusterBuilder } from '@justscale/cluster';
import { ChannelFeature } from '@justscale/channel';
import { ShellFeature } from '@justscale/feature-shell';
import { InMemoryChannelBackend } from '@justscale/channel';

const cluster = createClusterBuilder()
  .add(ShellFeature)
  .add(ChannelFeature)
  .add(InMemoryChannelBackend)
  .build();

await cluster.serve({ http: 3000 });

Feature Composition

Features compose cleanly and automatically integrate with each other. Features can declare dependencies on other features or abstract services, and JustScale validates these at build time.

What Features Provide

  • Services - Business logic and data access
  • Controllers - HTTP endpoints and CLI commands
  • Middleware - Request processing and guards
  • Dependencies - Automatic resolution of required features

Feature Benefits

  • Plug-and-play - Add complete functionality with one import
  • Type-safe - Dependencies validated at compile time
  • Testable - Features can be tested in isolation
  • Composable - Features work together seamlessly

Available Features

Channels (Pub/Sub)

The ChannelFeature provides pub/sub messaging with async iterables. It requires an abstract backend that you can satisfy with InMemoryChannelBackend or a Redis backend.

Interactive Shell

The ShellFeature provides an interactive REPL for your application. Think SSH, but you're connecting to the Node.js process itself to run commands and inspect state.

Datastar (SSE)

The Datastar integration provides Server-Sent Events streaming and reactive signal management for real-time updates.

Creating Custom Features

You can create your own features using createFeatureBuilder:

Files
src/features/my-feature.tsTypeScript
import { createFeatureBuilder, createService, createController } from '@justscale/core';
import { Get } from '@justscale/http';

const MyService = createService({
  inject: {},
  factory: () => ({
    getData: async () => ({ message: 'Hello from MyFeature!' }),
  }),
});

const MyController = createController('/my-feature', {
  inject: { myService: MyService },
  routes: (services) => ({
    data: Get('/data').handle(async ({ res }) => {
      const data = await services.myService.getData();
      res.json(data);
    }),
  }),
});

export const MyFeature = createFeatureBuilder()
  .name('my-feature')
  .provides((b) => b
    .service(MyService)
    .controller(MyController)
  );

Features with Dependencies

Features can declare dependencies on abstract services. The cluster builder validates that all dependencies are satisfied:

Files
src/features/notification-feature.tsTypeScript
import { createFeatureBuilder, createService, createAbstractServiceToken } from '@justscale/core';

// Abstract interface for notification backend
export const NotificationBackend = createAbstractServiceToken<{
  send: (userId: string, message: string) => Promise<void>;
}>('NotificationBackend');

const NotificationService = createService({
  inject: { backend: NotificationBackend },
  factory: ({ backend }) => ({
    notify: (userId: string, msg: string) => backend.send(userId, msg),
  }),
});

export const NotificationFeature = createFeatureBuilder()
  .name('notification')
  .requires(NotificationBackend)  // Declares dependency
  .provides((b) => b.service(NotificationService));