@ebca/cli
v0.0.12
Published
Command line tools for EBCA runtime inspection, reports, and transport contract generation.
Downloads
1,509
Maintainers
Readme
@ebca/cli
Runtime inspection and contract generation for EBCA applications.
@ebca/cli reads the metadata registered by @ebca/core decorators and turns a running or importable EBCA application into reports, graphs, ownership diagnostics, and generated transport contracts.
It is built for large event-driven systems where the architecture should be queryable instead of tribal knowledge.
Install
npm install --save-dev @ebca/cliThe CLI expects a project runtime module that imports/registers the application's EBCA entities, components, systems, read repositories, and contract declarations. Component admin commands also need the root Nest module or modules used by the application's real entrypoints, so the CLI can find the graph that provides ComponentManager.
Why It Exists
EBCA systems describe themselves at runtime. The CLI makes that metadata useful:
- see which systems listen to which lifecycle topics;
- inspect command workflows;
- find fan-out and multi-writer risks;
- check
@EbcaIOcoverage; - generate transport contracts from registered entities, components, queries, types, and enums;
- give AI agents a compact architecture map before they edit code.
Usage
Pass a runtime metadata module explicitly:
ebca report summary --runtime-module ./src/runtime.module.tsOr set it once in an npm script:
{
"scripts": {
"ebca": "EBCA_RUNTIME_MODULE=./src/runtime.module.ts ebca"
}
}Then run:
npm run ebca -- registry --json
npm run ebca -- links --with-io
npm run ebca -- graph --component PlaceOrderCommandComponent
npm run ebca -- report summary
npm run ebca -- report process --component PlaceOrderCommandComponent --depth 4
npm run ebca -- report boundary-risks
npm run ebca -- contract websocket --out ./src/contracts/ebca.generated.ts
npm run ebca -- contract graphql --out ./src/contracts/ebca.graphql.generated.tsRuntime Module Contract
A runtime module is project-owned. It should import the files that register EBCA decorators.
import './components/register-components';
import './systems/order.system';
import './queries/order-book.repository';
export async function loadProjectRuntimeMetadata(): Promise<void> {
await import('./orders/order.module');
}For component admin commands, return the root modules used by your real main.ts entrypoints. These should be the modules passed to NestFactory.create(...) or NestFactory.createMicroservice(...), not random feature modules:
import './components/register-components';
import { OrdersModule } from './orders/orders.module';
import { MarketModule } from './market/market.module';
export async function loadProjectRuntimeMetadata(): Promise<{
rootModules: readonly [typeof OrdersModule, typeof MarketModule];
}> {
await import('./orders/order.module');
await import('./market/market.module');
return {
rootModules: [OrdersModule, MarketModule],
};
}The CLI compiles these root modules and uses the first module graph that provides ComponentManager. When the project needs custom test overrides, the runtime module can still export a testing-module factory:
import { Test, TestingModule } from '@nestjs/testing';
import { AppModule } from './app.module';
export async function createEbcaComponentAdminTestingModule(): Promise<TestingModule> {
return Test.createTestingModule({
imports: [AppModule],
}).compile();
}The CLI never hardcodes your app folders or domain names.
Reports
| Command | Purpose |
| --- | --- |
| registry | Dump registered entities, components, systems, patterns, and queries. |
| links | List entity + event + component -> system.handler subscriptions. |
| graph | Render links as Mermaid or Graphviz DOT. |
| report summary | Compact overview of the runtime graph. |
| report process | Follow a command/fact workflow through emitted components. |
| report owners | Show who listens to, reads, writes, emits, or removes a component. |
| report risks | Find structural risks such as unhandled commands or hot fan-out. |
| report boundary-risks | Detect generic multi-writer ownership problems. |
| report io-coverage | Find handlers missing useful @EbcaIO declarations. |
| contract websocket | Generate a TypeScript transport contract for WebSocket consumers. |
| contract graphql | Generate a TypeScript transport contract for GraphQL queries, component mutations, snapshots, and subscriptions. |
Contract Generation
Generated contracts are based on runtime metadata:
@Entityand@Componentprovide entity/component names.- Entity and component source files provide payload shapes for generated classes.
@EbcaQueryand@EbcaQueryParamprovide query names and params; omitted querygatesexpose the query to every query transport, a non-empty list narrows it, andgates: []keeps the query internal.- Exported
type,interface, andenumdeclarations reachable from component/query imports provide reusable contract shapes. - Query result models can reference generated entity and component classes directly.
- Command component contracts include status, source (
system,websocket,rest,graphql), rejection reason, and failure details. - GraphQL contracts are TypeScript client/SDK contracts for the generic
ebcaQuery,ebcaComponentMutation,ebcaComponentRequest, andebcaComponentfields.
The CLI does not accept project-specific componentsRoot, typesRoot, or enumsRoot paths. If a type should be part of a generated contract, export it from the normal source graph used by a projected component or query repository.
Component Admin
The component get|add|update|upsert|remove commands call the real ComponentManager from your project module. Before running them, the CLI calls loadProjectRuntimeMetadata({ introspectionOnly: false }) when that hook exists, then tries the returned rootModules/startModules/modules, exported runtime module collections, exported Nest modules, and finally loaded project modules for backward compatibility. They are intended for operator/debug use and should not become normal business workflows.
License
Apache-2.0.
