Skip to content

ManuUseGitHub/aparte-cli

Repository files navigation

Aparté CLI

logo-art.png

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:

  1. Something an actor says to themselves on stage, intended only for the audience.
  2. 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.


aparte-boshi.png [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 gen

Create new schemes

$ npx aparte-cli schemes -c s1 [s2, s3, ... ,sN]

Invalidate cache

$ npx aparte-cli cache -i

Options

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.yml

Each YAML file represents a communication domain.

Concrete example : images/image-1.png

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.ts

Generated 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 the ROOT node
    • ROOT -> name of yaml files
    • from ROOT the 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):

  1. Action
  2. Scheme
  3. Outcome
  4. 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 images/example-data-scheme.png

Here is a registry of schemes + actions/event images/example-aparte-registry.png


MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors