aparte-cli
v1.1.0
Published
Generate strongly typed event registries, builders and IntelliSense-driven event messaging from YAML schemes.
Downloads
52
Maintainers
Readme
Aparté CLI

Helps event-driven communication with type-safe message discovery, YAML-powered registries, and IDE IntelliSense.
What is an Aparté?
Aparté is a French theatrical term with two meanings:
- Something an actor says to themselves on stage, intended only for the audience.
- A private conversation held aside from the main discussion.
The name reflects the purpose of this package: enabling structured communication between application components through an event bus while keeping messages organized, discoverable, and meaningful.
[TOC]
Why Aparté?
As applications grow, event-driven architectures often become difficult to maintain.
Event names are usually plain strings:
eventBus.emit('data.load.card');
eventBus.emit('data.load.cards');
eventBus.emit('load.card');
eventBus.emit('card.load');A small typo is enough to break communication.
Aparté solves this problem by:
- Defining event schemes in YAML.
- Generating strongly typed registries.
- Providing IntelliSense-driven event selection.
- Centralizing event definitions.
- Eliminating string guessing.
Quick Start
General command
$ npx aparte-cli { gen [-d generation-directory]
| schemes -c scheme1 [scheme2, ... schemeN]
| cache -u }
[-s]Generate
$ npx aparte-cli genCreate new schemes
$ npx aparte-cli schemes -c s1 [s2, s3, ... ,sN]Invalidate cache
$ npx aparte-cli cache -iOptions
| Option | Description |
| ------ | -------------------------------------------------- |
| -d | Output directory relative to the project root. |
| -s | Silent mode. Limits console output to the minimum. |
Project Structure
.aparte/
├── .json
├── sheme1.yml
├── scheme2.yml
├── ...
└── schemeN.ymlEach YAML file represents a communication domain.
Concrete example :

Minimal example of a scheme file:
ROOT:
GENERAL:
SPECIFICATION:
ACTION:Rules:
- Every scheme must start with
ROOT. - Leaves represent actions/events.
- the value should not be specified to make aparté simple of use.
- Intermediate nodes represent navigation paths.
Generation
src/aparte/
├── aparte.builder.ts
├── aparte.composites.ts
├── aparte.decorators.ts
├── aparte.registry.json
└── aparte.registry.tsGenerated artifacts include:
- Registries that mirror your schemes
- Builders to leverage the registries
- Composites from your schemes files splitting actions of schemes
- Event enums (
EV) or events/actions - Branch enums (
BR) for branches or schemes from theROOTnodeROOT-> name of yaml files- from
ROOTthe rest of tree branches to your actions
IntelliSense-Driven Messaging
After generation, events become discoverable directly from your IDE.
Instead of remembering strings:
eventBus.emit('data.load_card.all');You compose messages using generated definitions and enums:
Aparte.hi5({ ALL: 'data.load_card' });Benefits:
- Autocompletion
- Refactoring support
- Reduced typo risk
- Better discoverability
Communication Model
With aparté we technically bundle, methods for defining the nature to communicate alongside the registry generation mechanism to help the decision ( 1️⃣ what action is listen to of 2️⃣ which scheme if it is 3️⃣ good 🟢 or bad 🔴 or outcome or on going state (neutral) 🟠 and 4️⃣ - 🐞 for debug purpose - if it is log-able (loud 🔈) or not (silent 🔇)).
Messages encode (combination):
- Action
- Scheme
- Outcome
- Visibility
Outcomes
| State | Meaning | | ----- | ------- | | 🟢 | Success | | 🟠 | Ongoing | | 🔴 | Failure |
Visibility
| Type | Meaning | | -------- | ---------------- | | 🔈 Loud | Visible in logs | | 🔇 Silent | Hidden from logs |
Usage
For reference you have acess to these forms of method calls:
Aparte.<communication method>({ 1️⃣ : '2️⃣' });
// producing a result of
// - 3️⃣ 🟢 good outcome/ 🔴 bad outcome/ 🟠 neutral/doing/ongoing state
// - 4️⃣ 🔇 silent (never shouted in the log) / 🔈 loud (for debugging)This mechanisme will produce a string at the end that caracterize a message as such:
- starting by
_: silent message- else ; loud message
- ending by
_OK: good outcome_KO: bad outcome- neither : neutral state (not finished)
Broadcasting
Whenever you want to communicate, think of these actions. An actor (a component) can perform to captivate (through the event bus) the attention of the other actors (components that may interract)
Aparte.nod({ LOAD_CARD: 'data.load_card' }); // 🔇 + 🟢
Aparte.hi5({ LOAD_CARD: 'data.load_card' }); // 🔈 + 🟢
Aparte.touch({ LOAD_CARD: 'data.load_card' }); // 🔇 + 🟠
Aparte.pinch({ LOAD_CARD: 'data.load_card' }); // 🔈 + 🟠
Aparte.bother({ LOAD_CARD: 'data.load_card' }); // 🔇 + 🔴
Aparte.tickle({ LOAD_CARD: 'data.load_card' }); // 🔈 + 🔴Listening
Accordingly, methods are bundled to listen for outcomes and state of action in a scheme. note: the loudness dissapear from the concept since it only concerns logging.
Aparte.satisfied({ LOAD_CARD: 'data.load_card' }); // 🟢
Aparte.doing({ LOAD_CARD: 'data.load_card' }); // 🟠
Aparte.disappointed({ LOAD_CARD: 'data.load_card' });// 🔴Philosophy
Define communication once in YAML and let tooling generate the rest.
The result is:
- Consistent event naming
- Strong typing
- Better scalability
- Safer refactoring
- Improved developer experience
- Centralized event governance
Examples
Here is an example of a scheme for data that you can design in case you want to manage a part of a flash card application

Here is a registry of schemes + actions/event

