npm package: @omen.foundation/node-microservice-runtime
Description: Beamable microservice runtime for Node.js/TypeScript services.
Latest version: 0.1.123

# @omen.foundation/node-microservice-runtime

TypeScript/Node.js runtime for **Beamable** microservices: WebSocket gateway integration, dependency injection, OpenAPI generation, MongoDB storage helpers, optional federation, logging (OpenTelemetry / collector), and a **`beamo-node`** CLI for validate/publish workflows.

## Requirements

- **Node.js** `>= 22.14.0` (see `engines` in `package.json`).
- **ESM** projects: `"type": "module"` in your service `package.json`.
- **`reflect-metadata`** imported once before any decorated classes load (required for decorators / DI).

## Install

```bash
npm install @omen.foundation/node-microservice-runtime reflect-metadata
```

The package ships:

- **Library** — decorators, `runMicroservice()`, DI tokens, storage/federation helpers.
- **CLI** — `beamo-node` (login, scaffold, validate, publish, …).

## Minimal service shape

1. **`package.json`** — declare the Beamable service id (must match `@Microservice` name):

```json
{
  "name": "my-game-service",
  "type": "module",
  "main": "dist/main.js",
  "scripts": {
    "dev": "tsx --env-file .env src/main.ts",
    "build": "tsc -p tsconfig.json",
    "validate": "npx beamo-node validate --env-file .env",
    "publish": "npx beamo-node publish --env-file .env"
  },
  "beamable": {
    "beamoId": "MyGameService",
    "projectType": "service"
  }
}
```

2. **Entry file** — load metadata, import the class that carries `@Microservice`, then start:

```ts
import 'reflect-metadata';
import './MyGameService.js';
import { runMicroservice } from '@omen.foundation/node-microservice-runtime';

void runMicroservice();
```

3. **Service class** — exactly one class decorated with `@Microservice('Name')` (name must match `beamable.beamoId`).

## Decorators and HTTP access

| Decorator | Typical use |
|-----------|-------------|
| `@Microservice('ServiceName')` | Registers the service (required, one per process). |
| `@Callable` | General callable; access via `access` option or use a specialized decorator below. |
| `@ClientCallable` | Game/client calls; expects authenticated user. |
| `@ServerCallable` | Trusted server-to-server style routes. |
| `@AdminCallable` | Admin-scoped routes. |
| `@ConfigureServices` | Static method receiving `DependencyBuilder` — register singletons, factories. |
| `@InitializeServices` | Static method receiving scope — run after container is built. |
| `@SwaggerCategory` / `@SwaggerTags` | OpenAPI grouping. |
| `@StorageObject('StorageName')` | Registers a named Beamable storage binding (MongoDB). |
| `@FederatedInventory` | Optional federation hook for inventory-style flows. |

Handlers receive **`RequestContext`** (`userId`, `cid`, `pid`, logger, `provider` for DI resolution, etc.).

## Environment: Beamable vs `beam.env`

### Required for a running service

The runtime calls `loadEnvironmentConfig()`, which **requires**:

- `CID` — customer id  
- `PID` — project / realm id  
- `HOST` — WebSocket host (e.g. `wss://api.beamable.com/socket`)  
- `SECRET` — signing secret (when used by your deployment; local CLI may use tokens instead)

Optional common variables include `REFRESH_TOKEN`, `NAME_PREFIX` / `ROUTING_KEY`, `LOG_LEVEL`, `HEALTH_PORT` (defaults to **6565** when not set or invalid).

### Developer file: `beam.env`

The runtime loads **`beam.env`** (or **`.beam.env`**) from, in order:

1. `process.cwd()/beam.env` or `.beam.env`
2. `/beam/service/beam.env` or `.beam.env` (typical container layout)

Rules:

- Format: `KEY=value`, `#` comments, optional quotes for values.
- **Does not override** variables already in `process.env`.

See the published **`beam.env.example`** in this package for a starting template.

### Beamable Config API

Config from the portal can be merged in asynchronously (with a short timeout). Keys are exposed as `BEAM_CONFIG_*`. Details are summarized in **`AGENTS.md`** and **`ai/RUNTIME_FOR_AI.md`**.

### OpenAPI / validate / publish without starting the server

Tools set:

```bash
BEAMABLE_SKIP_RUNTIME=true
```

so `runMicroservice()` returns immediately while your module graph still loads for schema generation.

## Docker (production-oriented)

Recommended patterns used in production games:

1. **Working directory** — use **`/beam/service`** so the default `beam.env` search path matches the runtime.
2. **Copy artifacts** — `dist/`, `package.json`, lockfile, `beam_openApi.json` (if generated), and **`beam.env`** (or inject secrets via orchestrator and skip copying secrets into images where policy forbids it).
3. **Health checks** — expose the HTTP health port (default **6565**, overridable with `HEALTH_PORT`).
4. **Collector startup** — pre-installing the Beamable OpenTelemetry collector under **`/opt/beam/collectors/...`** avoids a multi-second download on cold start. See **`ai/RUNTIME_FOR_AI.md`** for an example multi-stage `Dockerfile` fragment.

Your game may use Node 20 images today; the **runtime’s declared engine is Node 22+** — align image version with `engines` before upgrading the dependency.

## CLI: `beamo-node`

Installed as a binary with the package:

```bash
npx beamo-node --help
```

Typical project scripts:

```bash
npx beamo-node validate --env-file .env
npx beamo-node publish --env-file .env
```

Login and scaffolding commands create a local profile under `~/.beamo-node/`.

**`beamo-node scaffold <name>`** creates a new project that includes **`AGENTS.md`**, **`CLAUDE.md`**, **`ai/`** (reference docs), **`.cursor/rules/beamable-node-microservice.mdc`**, and a short **`README.md`** pointing at those files.

## TypeScript

Enable decorator metadata in `tsconfig.json`:

```json
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "target": "ES2022"
  }
}
```

## MongoDB / `@StorageObject`

- Decorate a class with `@StorageObject('MyStorage')`.
- Connection string env var: **`STORAGE_CONNSTR_<MyStorage>`** (see runtime `StorageService` — name is normalized).
- Optional pool sizing: **`MONGODB_MAX_POOL_SIZE`** (clamped).

Import storage classes **before** services that depend on them so decorators register.

## AI assistants / agents

This package includes **`AGENTS.md`** (short rules), **`CLAUDE.md`** (index for AI tools), and **`ai/RUNTIME_FOR_AI.md`** (deep reference: Dockerfile, env, pitfalls). Point Cursor, Claude Code, Codex, or other tools at those files when generating or refactoring Beamable Node microservices. Optional Cursor rule text lives in **`ai/cursor-rule-snippet.md`**.

## License

MIT