Nourishing Pizza Microservice

    ajwahjs
    TypeScript icon, indicating that this package has built-in type declarations

    1.3.5 • Public • Published

    ajwahjs

    Framework agnostic state management tool without ceremonies and boilerplates.

    Reactive state management library. Manage your application's states, effects, and actions easy way. Make apps more scalable with a unidirectional data-flow.

    Every StateController has the following features:

    • Dispatching actions
    • Filtering actions
    • Adding effects
    • Communications among Controllers[Although they are independents]

    CounterState

    interface CounterState {
      count: number;
      loading: bool;
    }
    
    class CounterStateCtrl extends StateController<CounterState> {
      constructor() {
        super({ count: 0, loading: false });
      }
      onInit() {}
    
      inc() {
        this.emit({ count: this.state.count++ });
      }
    
      dec() {
        this.emit({ count: this.state.count-- });
      }
    
      async asyncInc() {
        this.emit({ loading: true });
        await delay(1000);
        this.emit({ count: this.state.count++, loading: false });
      }
    
      asyncIncBy = effect<number>((num$) =>
        num$.pipe(
          tap((_) => this.emit({ loading: true })),
          delay(1000),
          tap((by) => this.emit({ count: this.state.count + by, loading: false }))
        )
      );
    }

    Consuming State in

    Vanilla js

    const csCtrl = Get(CounterStateCtrl);
    csCtrl.stream$.subscrie(console.log);
    csCtrl.inc();
    csCtrl.dec();
    csCtrl.asyncInc();
    csCtrl.asyncIncBy(5);

    React

    const CounterComponent = () => {
      const csCtrl = Get(CounterStateCtrl);
    
      const data = useStream(csCtrl.stream$, csCtrl.state);
    
      return (
        <p>
          <button className="btn" onClick={() => csCtrl.inc()}>
            +
          </button>
          <button className="btn" onClick={() => csCtrl.dec()}>
            -
          </button>
          <button className="btn" onClick={() => csCtrl.asyncInc()}>
            async(+)
          </button>
          {data.loading ? 'loading...' : data.count}
        </p>
      );
    };

    Angular

    @Component({
      selector: 'app-counter',
      template: `
        <p>
          <button class="btn" (click)="csCtrl.inc()">+</button>
          <button class="btn" (click)="csCtrl.dec()">-</button>
          <button class="btn" (click)="csCtrl.asyncIn())">async(+)</button>
          <span *ngIf="csCtrl.stream$ | async as state"
            >{{ state.loading ? 'loading...' : state.count }}
          </span>
        </p>
      `,
      changeDetection: ChangeDetectionStrategy.OnPush,
    })
    export class CounterComponent {
      constructor(public csCtrl: CounterStateCtrl) {}
    }

    Vue

    <template>
      <p>
        <button class="btn" @click="inc()">+</button>
        <button class="btn" @click="dec()">-</button>
        <button class="btn" @click="asyncInc()">async(+)</button>
        {{ state.loading?'loading...':state.count }}
      </p>
    </template>
    
    export default {
      name: "Counter",
      components: {},
      setup() {
        const csCtrl = Get(CounterStateCtrl);
    
        const state = useStream(csCtrl.stream$, csCtrl.state);
    
        function inc() {
          csCtrl.inc();
        }
        function dec() {
          csCtrl.dec();
        }
        function asyncInc() {
          csCtrl.asyncInc();
        }
    
        return { inc, dec, asyncInc, state };
      },
    };

    Effects

    onInit() {
        this.effectOnAction(
          this.action$.isA(AsyncInc).pipe(
            tap((_) => this.emit({ loading: true })),
            delay(1000),
            map((action) => ({ count: this.state.count + action.data, loading: false  }))
        ));
    }
    
    asyncIncBy = effect<number>((num$) =>
      num$.pipe(
        tap((_) => this.emit({ loading: true })),
        delay(1000),
        tap((by) => this.emit({ count: this.state.count + by, loading: false }))
      )
    );

    Combining States

     get todos$() {
        return combineLatest([
          this.stream$,
          this.remoteStream<SearchCategory>(SearchCategoryStateCtrl)
        ]).pipe(
          map(([todos, searchCategory]) => {
            switch (searchCategory) {
              case SearchCategory.active:
                return todos.filter(todo => !todo.completed);
              case SearchCategory.completed:
                return todos.filter(todo => todo.completed);
              default:
                return todos;
            }
          })
        );
      }

    counter : Angular Demo | React Demo | Vue Demo

    todos : Angular Demo | React Demo | Vue Demo

    Install

    npm i ajwahjs

    DownloadsWeekly Downloads

    100

    Version

    1.3.5

    License

    ISC

    Unpacked Size

    132 kB

    Total Files

    20

    Last publish

    Collaborators

    • jukhan