ng-commander
Version:
Command pattern for Angular applications
187 lines (180 loc) • 7.79 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, NgModule } from '@angular/core';
import { BehaviorSubject, Subject, concatMap, catchError } from 'rxjs';
var CommandEventType;
(function (CommandEventType) {
CommandEventType["START"] = "start";
CommandEventType["SUCCESS"] = "success";
CommandEventType["FAIL"] = "fail";
CommandEventType["RESTART"] = "restart";
})(CommandEventType || (CommandEventType = {}));
var CommanderState;
(function (CommanderState) {
CommanderState[CommanderState["IDLE"] = 0] = "IDLE";
CommanderState[CommanderState["EXECUTING"] = 1] = "EXECUTING";
CommanderState[CommanderState["DONE"] = 2] = "DONE";
CommanderState[CommanderState["ERROR"] = 3] = "ERROR";
})(CommanderState || (CommanderState = {}));
var CommandsType;
(function (CommandsType) {
CommandsType[CommandsType["WAITING"] = 0] = "WAITING";
CommandsType[CommandsType["DONE"] = 1] = "DONE";
CommandsType[CommandsType["ERROR"] = 2] = "ERROR";
})(CommandsType || (CommandsType = {}));
class Commander {
// Use BehaviorSubjects instead of arrays
commandsSubject = new BehaviorSubject([]);
commandsDoneSubject = new BehaviorSubject([]);
commandsInErrorSubject = new BehaviorSubject([]);
stateSubject = new BehaviorSubject(CommanderState.IDLE);
// Nouveau sujet pour les événements de commande
eventsSubject = new BehaviorSubject([]);
processingCommand = new Subject();
// Expose as Observables
commands$ = this.commandsSubject.asObservable();
commandsDone$ = this.commandsDoneSubject.asObservable();
commandsInError$ = this.commandsInErrorSubject.asObservable();
state$ = this.stateSubject.asObservable();
events$ = this.eventsSubject.asObservable();
constructor() {
this.processingCommand
.pipe(concatMap(({ command }) => {
this.stateSubject.next(CommanderState.EXECUTING);
// Ajouter un événement START
this.trackEvent(CommandEventType.START, command);
return command.execute().pipe(concatMap((result) => {
return [{ command, result, isError: false }];
}), catchError((error) => {
return [{ command, error, isError: true }];
}));
}))
.subscribe({
next: (data) => {
if (data.isError) {
this.stateSubject.next(CommanderState.ERROR);
const currentErrors = this.commandsInErrorSubject.value;
this.commandsInErrorSubject.next([...currentErrors, data.command]);
// Ajouter un événement FAIL avec l'erreur si disponible
this.trackEvent(CommandEventType.FAIL, data.command, 'error' in data ? data.error : undefined);
}
else {
this.stateSubject.next(CommanderState.DONE);
const currentDone = this.commandsDoneSubject.value;
this.commandsDoneSubject.next([...currentDone, data.command]);
// Ajouter un événement SUCCESS avec le résultat si disponible
this.trackEvent(CommandEventType.SUCCESS, data.command, 'result' in data ? data.result : undefined);
}
this.executeNextCommand();
},
error: (errorObj) => {
this.stateSubject.next(CommanderState.ERROR);
this.executeNextCommand();
},
});
}
addCommand(command) {
// Initialiser le tableau d'événements si nécessaire
if (!command.events) {
command.events = [];
}
const currentCommands = this.commandsSubject.value;
this.commandsSubject.next([...currentCommands, command]);
if (currentCommands.length === 0) {
this.executeNextCommand();
}
}
replayCommandsInError() {
const commandsInError = this.commandsInErrorSubject.value;
this.commandsInErrorSubject.next([]);
if (commandsInError.length > 0) {
// Ajouter un événement RESTART pour chaque commande
commandsInError.forEach((command) => {
this.trackEvent(CommandEventType.RESTART, command);
});
this.commandsSubject.next(commandsInError);
this.executeNextCommand();
}
}
getCommands(type) {
switch (type) {
case CommandsType.WAITING:
return this.commandsSubject.value;
case CommandsType.DONE:
return this.commandsDoneSubject.value;
case CommandsType.ERROR:
return this.commandsInErrorSubject.value;
}
}
getState() {
return this.stateSubject.value;
}
// Obtenir tous les événements
getEvents() {
return this.eventsSubject.value;
}
// Obtenir les événements pour une commande spécifique
getCommandEvents(commandId) {
return this.eventsSubject.value.filter((event) => event.command.id === commandId);
}
// Méthode privée pour tracer un événement
trackEvent(type, command, data) {
const event = {
type,
command,
data,
timestamp: new Date(),
};
// Ajouter l'événement à la collection globale
const currentEvents = this.eventsSubject.value;
this.eventsSubject.next([...currentEvents, event]);
// Ajouter l'événement à la commande elle-même
if (!command.events) {
command.events = [event];
}
else {
command.events.push(event);
}
}
executeNextCommand() {
const currentCommands = this.commandsSubject.value;
if (currentCommands.length > 0) {
const [command, ...rest] = currentCommands;
this.commandsSubject.next(rest);
this.stateSubject.next(CommanderState.EXECUTING);
this.processingCommand.next({ command, result: null });
}
else {
this.stateSubject.next(CommanderState.IDLE);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: Commander, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: Commander, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: Commander, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [] });
class NgCommanderModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgCommanderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: NgCommanderModule });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgCommanderModule, providers: [Commander] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgCommanderModule, decorators: [{
type: NgModule,
args: [{
declarations: [],
imports: [],
providers: [Commander],
exports: [],
}]
}] });
/*
* Public API Surface of ng-commander
*/
/**
* Generated bundle index. Do not edit.
*/
export { Commander, CommanderState, CommandsType, NgCommanderModule };
//# sourceMappingURL=ng-commander.mjs.map