# NgCommander

NgCommander is an Angular library implementing the Command Pattern for Angular applications. It provides a clean way to manage async operations, track their state, and handle errors.

## Features

- Queue commands for sequential execution
- Track command state (waiting, executing, done, error)
- Manage command execution history
- Retry failed commands
- Observable-based API for reactive applications

## Installation

```bash
npm install ng-commander
```

Or with yarn:

```bash
yarn add ng-commander
```

## Usage

First, import the NgCommanderModule in your application module:

```typescript
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { NgCommanderModule } from "ng-commander";
import { AppComponent } from "./app.component";

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, NgCommanderModule],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

Then, create a command by implementing the Command interface:

```typescript
import { Command } from "ng-commander";
import { Observable, of, delay } from "rxjs";

export class SampleCommand implements Command<string> {
  id: string;

  constructor(id: string) {
    this.id = id;
  }

  execute(): Observable<string> {
    // Your command logic here
    return of(`Result from command ${this.id}`).pipe(
      delay(1000) // Simulate async operation
    );
  }
}
```

Finally, inject and use the Commander service in your components:

````typescript
import { Component, OnInit } from '@angular/core';
import { Commander, CommanderState } from 'ng-commander';
import { SampleCommand } from './sample.command';

@Component({
  selector: 'app-root',
  template: `
    <div>
      <h2>Current State: {{ getStateText() }}</h2>
      <button (click)="addCommand()">Add Command</button>
    </div>
  `
})
export class AppComponent implements OnInit {
  currentState: CommanderState = CommanderState.IDLE;

  constructor(private commander: Commander) {}

  ngOnInit() {
    this.commander.state$.subscribe(state => {
      this.currentState = state;
    });
  }

  addCommand() {
    const command = new SampleCommand(`cmd-${Date.now()}`);
    this.commander.addCommand(command);
  }

  getStateText(): string {
    return CommanderState[this.currentState];
  }
}

## API Reference

### Commander Service

The core service that manages command execution.

#### Properties

- `commands$`: Observable of commands waiting to be executed
- `commandsDone$`: Observable of successfully executed commands
- `commandsInError$`: Observable of commands that failed during execution
- `state$`: Observable of the current command processor state

#### Methods

- `addCommand<C>(command: Command<C>)`: Add a command to the execution queue
- `replayCommandsInError()`: Re-queue commands that previously failed
- `getCommands(type: CommandsType)`: Get commands by their current status
- `getState()`: Get the current state of the command processor

### CommanderState Enum

Represents the possible states of the command processor:

- `IDLE`: No commands are currently executing
- `EXECUTING`: A command is currently being executed
- `DONE`: A command has been successfully completed
- `ERROR`: A command has failed during execution

### CommandsType Enum

Used to filter commands by their current status:

- `WAITING`: Commands waiting to be executed
- `DONE`: Successfully executed commands
- `ERROR`: Commands that failed during execution

## Building and Contributing

To build the library:

```bash
npm run build:lib
````

To run tests:

```bash
npm test
```

## License

MIT
